messagingfw/msgsrvnstore/server/src/msvdbadapter.cpp
changeset 0 8e480a14352b
child 6 fe71b07a6401
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/msvdbadapter.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,4756 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// HEADER FILES
+// 
+//
+
+
+/**
+ * HEADER FILES
+ */
+#include <barsc.h>
+#include <bautils.h>
+
+#include "msvdbadapter.h"
+#include "msventryfreepool.h"
+#include "msvsearchsortdbwrapper.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "msvsearchsortconstants.h"
+#endif
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	#include "cmessageconvertermanager.h"
+#endif
+
+/**
+ * CONSTANT DEFINITION
+ */
+#define SERVER_UID 0x1000484B
+#define KMsvNumStdFolder 7
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	#include "msvindexadapter.h"
+	
+	//Main (dummy) DB name.
+	#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+		_LIT(KMainDummyDBName, "\\messaging_master.db");
+		_LIT(KMessagingDBName, "\\messaging.db");
+	#else
+		_LIT(KMainDummyDBName, "[1000484b]messaging_master.db");
+		_LIT(KMessagingDBName, "[1000484b]messaging.db");
+	#endif
+
+	_LIT(KLogicalName, "DB");
+	_LIT(KComma, ", ");
+	_LIT(KDelimiter, " ;");
+#endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+
+/**
+ * LITERAL DEFINITION
+ */
+//Data definition queries
+_LIT8(KEncodingText, "encoding=UTF-8");
+_LIT8(KCreateIndexEntryTableQuery,	"CREATE TABLE IF NOT EXISTS IndexEntry ("
+								"id INTEGER PRIMARY KEY,"
+						  		"parentId INT,"
+								"serviceId INT,"
+								"mtmId INT,"
+								"type INT,"
+								"date INT64,"
+								"data INT,"
+								"size INT,"
+								"error INT,"
+								"mtmData1 INT,"
+								"mtmData2 INT,"
+								"mtmData3 INT,"
+								"relatedId INT,"
+								"bioType INT,"
+								"pcSyncCount INT,"
+								"reserved INT,"
+								"visibleParent INT,"
+								"description TEXT,"
+						  		"details TEXT" ");"
+	  );
+	  
+_LIT8(KCreateIndexQuery, "CREATE INDEX IF NOT EXISTS INDEX_PARENT ON IndexEntry(parentId);");
+_LIT8(KCreateVersionTableQuery, "CREATE TABLE IF NOT EXISTS VersionTable ( "
+									"version INTEGER PRIMARY KEY );"
+		);
+	
+//Common database queries
+_LIT8(KGetEntryExistsQuery, "SELECT parentId FROM IndexEntry WHERE id = :id;"); //
+_LIT8(KGetVisibleIdQuery, "SELECT data, visibleParent FROM IndexEntry WHERE id = :id;"); //
+_LIT8(KGetEntryQuery, "SELECT parentId, serviceId, mtmId, type, date, data, size, error, "
+						"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+						"reserved, visibleParent, description, details FROM IndexEntry WHERE id = :id;"); //
+_LIT8(KGetChildEntriesQuery, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
+							"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+							"reserved, visibleParent, description, details FROM IndexEntry "
+							"WHERE parentId = :parentId order by id ASC;"); //
+		
+//Data manipulation queries
+_LIT8(KCreateEntryQuery,	 "INSERT INTO IndexEntry VALUES ("
+							 ":id, :parentId, :serviceId, :mtmId, :type, :date, :data, :size, :error,"
+							 ":mtmData1, :mtmData2, :mtmData3, :relatedId, :bioType, :pcSyncCount,"
+							 ":reserved, :visibleParent, :description, :details);"
+	 ); //
+_LIT8(KUpdateEntryQuery,	"UPDATE IndexEntry SET "
+							"parentId = :parentId, serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
+							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
+							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
+							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
+							"details = :details WHERE id = :id;"
+	 ); //
+_LIT8(KUpdateEntryNoParentQuery,	"UPDATE IndexEntry SET "
+							"serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
+							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
+							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
+							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
+							"details = :details WHERE id = :id;"
+	 ); //
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+_LIT8(KCreateConversionStatusTableQuery, 	"CREATE TABLE IF NOT EXISTS ConversionStatus ("
+								"lastId INT,"
+						  		"serviceId INTEGER PRIMARY KEY,"
+								"sourceVersion INT,"
+								"targetVersion INT,"
+								"mtmId INT,"
+								"remainingCount INT );"
+	 );	
+
+_LIT8(KRemoveConversionStatusTable,  "DROP TABLE IF EXISTS ConversionStatus;");					
+
+
+
+#endif
+	 
+	 
+//Literals for parameter indexes
+_LIT(KMsgParamId, ":id");
+_LIT(KMsgParamParentId, ":parentId");
+_LIT(KMsgParamServiceId, ":serviceId");
+_LIT(KMsgParamMtmId, ":mtmId");
+_LIT(KMsgParamType, ":type");
+_LIT(KMsgParamDate, ":date");
+_LIT(KMsgParamData, ":data");
+_LIT(KMsgParamSize, ":size");
+_LIT(KMsgParamError, ":error");
+_LIT(KMsgParamMtmData1, ":mtmData1");
+_LIT(KMsgParamMtmData2, ":mtmData2");
+_LIT(KMsgParamMtmData3, ":mtmData3");
+_LIT(KMsgParamRelatedId, ":relatedId");
+_LIT(KMsgParamBiotype, ":bioType");
+_LIT(KMsgParamPcSyncCount, ":pcSyncCount");
+_LIT(KMsgParamReserved, ":reserved");
+_LIT(KMsgParamVisibleParent, ":visibleParent");
+_LIT(KMsgParamDescriptionTxt, ":description");
+_LIT(KMsgParamDetailsTxt, ":details");
+
+//Literals for column indexes
+_LIT(KMsgColumnId, "id");
+_LIT(KMsgColumnParentId, "parentId");
+_LIT(KMsgColumnServiceId, "serviceId");
+_LIT(KMsgColumnMtmId, "mtmId");
+_LIT(KMsgColumnType, "type");
+_LIT(KMsgColumnDate, "date");
+_LIT(KMsgColumnData, "data");
+_LIT(KMsgColumnSize, "size");
+_LIT(KMsgColumnError, "error");
+_LIT(KMsgColumnMtmData1, "mtmData1");
+_LIT(KMsgColumnMtmData2, "mtmData2");
+_LIT(KMsgColumnMtmData3, "mtmData3");
+_LIT(KMsgColumnRelatedId, "relatedId");
+_LIT(KMsgColumnBiotype, "bioType");
+_LIT(KMsgColumnPcSyncCount, "pcSyncCount");
+_LIT(KMsgColumnReserved, "reserved");
+_LIT(KMsgColumnVisibleParent, "visibleParent");
+_LIT(KMsgColumnDescriptionTxt, "description");
+_LIT(KMsgColumnDetailsTxt, "details");
+
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	_LIT8(KGetChildIdsQuery, "SELECT id, type, data FROM IndexEntry WHERE parentId = :parentId order by id ASC;"); //
+	_LIT8(KClearTableContents, "DELETE FROM SearchSortEntry;");
+#else
+	_LIT8(KDeleteTable,  "DROP TABLE IF EXISTS SearchSortEntry;");
+	_LIT8(KGetChildIdsQuery, "SELECT id FROM IndexEntry WHERE parentId = :parentId order by id ASC;"); //
+	_LIT8(KGetInPreparationIdQuery, "SELECT id, data FROM IndexEntry;");
+#endif
+
+
+
+// Changes for PREQ 1667.
+//Data definition queries for SearchSort-Table
+_LIT8(KCreateSearchSortEntryTableQuery,	"CREATE TABLE IF NOT EXISTS SearchSortEntry ("
+						"Qid INT,"
+				  		"id INT,"
+						"sortfield TEXT" ");"
+);
+
+_LIT8(KCreateSearchSortQuery, "CREATE UNIQUE INDEX IF NOT EXISTS SearchSortEntry_UNIQUE ON SearchSortEntry (Qid, id,sortfield);");
+
+//Common database queries
+_LIT8(KGetEntryAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by sortfield ASC;");
+_LIT8(KGetEntryDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by sortfield DESC;");
+_LIT8(KGetEntryNumAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by CAST(sortfield AS INT) ASC;");
+_LIT8(KGetEntryNumDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by CAST(sortfield AS INT) DESC;");
+
+_LIT8(KGetLastNIdsAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by sortfield ASC;");
+_LIT8(KGetLastNIdsDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by sortfield DESC;");
+_LIT8(KGetLastNIdsNumAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by CAST(sortfield AS INT) ASC;");
+_LIT8(KGetLastNIdsNumDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by CAST(sortfield AS INT) DESC;");
+
+_LIT8(KGetQueryCount, "SELECT COUNT(DISTINCT id) FROM SearchSortEntry WHERE Qid = :Qid");
+
+_LIT8(KGetFolderIds, "SELECT id FROM IndexEntry WHERE parentId = :parentId AND type LIKE :type");
+
+_LIT8(KGetIterResultCastAsc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by CAST(sortfield AS INT) ASC LIMIT :lim OFFSET :off ");
+_LIT8(KGetIterResultCastDesc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by CAST(sortfield AS INT) DESC LIMIT :lim OFFSET :off ");
+_LIT8(KGetIterResultAsc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by sortfield ASC LIMIT :lim OFFSET :off ");
+_LIT8(KGetIterResultDesc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by sortfield ASC LIMIT :lim OFFSET :off ");
+
+//Data manipulation queries
+_LIT8(KDeleteId, 	 "DELETE FROM SearchSortEntry WHERE id = ");
+_LIT8(KCreateQueryEntry,	 "INSERT OR IGNORE INTO SearchSortEntry VALUES ("
+							 ":Qid, :id, :sortfield);");
+
+_LIT8(KDeleteQueryId, 	 "DELETE FROM SearchSortEntry WHERE Qid = ");
+_LIT8(KAndId, " AND id = ");
+_LIT8(KSemiColon, ";");
+
+//Literals for parameter indexes
+_LIT(KQueryQId, ":Qid");
+_LIT(KQueryTMsvId, ":id");
+_LIT(KQuerySortfield, ":sortfield");
+_LIT(KQueryRowId, ":RowId");
+_LIT(KOffset, ":off");
+_LIT(KLimit, ":lim");
+
+//Literals for column indexes
+_LIT(KQueryColumnTMsvId, "id");
+
+
+
+/**
+ * MEMBER FUNCTIONS OF CMsvDBAdapter
+ */
+
+
+
+/**
+ * CMsvDBAdapter()
+ * The default Constructor. 
+ */
+CMsvDBAdapter::CMsvDBAdapter():isTransactionOpen(EFalse)
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		,iDbPtrInitialized(EFalse)
+#endif
+	{
+	}
+
+
+
+
+/**
+ * ~CMsvDBAdapter()
+ * The default Destructor. 
+ */
+CMsvDBAdapter::~CMsvDBAdapter()
+	{
+	//Close all RSqlStatement object.
+	for(TInt index = ECreateEntry; index < EIndexSentinel; index++)
+		{
+		iStatement[index].Close();
+		}
+
+	for(TInt index = EQueryCreateEntry; index < EQuerySentinel; index++)
+		{
+		iQueryStatement[index].Close();
+		}
+		
+	iDatabase.Close();
+	
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	if(iDatabasePresent)
+		{
+		iDatabasePresent->Close();
+		delete iDatabasePresent;
+		}
+#endif
+	}
+
+
+
+
+// Code added in PREQ 557.
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+/**
+ * NewL()
+ * @param None.
+ * @return None.
+ * 
+ * Allocates and constructs a new DBAdapter object, calls ConstructL 
+ * to create the dummy database and returns a handle to the DBAdapter.
+ */
+CMsvDBAdapter* CMsvDBAdapter::NewL()
+	{
+	//Create the DBAdapter object.
+	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
+	CleanupStack::PushL(self);
+	
+	// Create the database.
+	self->ConstructL();
+	
+	CleanupStack::Pop(self);
+	return self;
+	
+	}
+
+
+
+
+/**
+ * ConstructL()
+ * @param None.
+ * @return None.
+ * 
+ * Checks if there is the main (dummy) DB in the system drive
+ * and creates one if it is not present. Other databases will
+ * be attached to this DB which will not get deleted during
+ * the operation of the message server.
+ */
+void CMsvDBAdapter::ConstructL()
+	{
+	//Get the system drive.
+	TInt systemDrive = (TInt)RFs::GetSystemDrive();
+	
+	RBuf dbFile;
+	CleanupClosePushL(dbFile);
+	dbFile.CreateL(50);	
+	dbFile.Append(TDriveUnit(systemDrive).Name());
+	dbFile.Append(KMainDummyDBName);
+	
+	//Check if the main DB exists. If not, then create it.
+	// > KErrNotFound, KErrPathNotFound - DB doesn't exist.
+	// > KErrNone, KErrInUse - DB exists.
+	TRAPD(err, iDatabase.OpenL(dbFile));
+	if(KErrNone != err)
+		{
+		
+		// Leave in unfavorable condition.
+		if(KErrNoMemory == err ||
+		   KErrNotReady == err ||
+		   KErrInUse    == err
+		  )
+			{
+			User::Leave(err);
+			}
+
+		HBufC8* heapBuf = KEncodingText().AllocLC();
+		
+		if(KSqlErrCorrupt == err || KSqlErrNotDb == err)
+			{
+			RSqlDatabase::Delete(dbFile);
+			}
+		
+		//Create the dummy DB.		
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+		// Create the non-secure database.
+		User::LeaveIfError(iDatabase.Create(dbFile, heapBuf));
+#else
+		// Using SID based security policy.
+		TSecureId sid(SERVER_UID);
+		const TSecurityPolicy KDefaultPolicy(sid);
+	
+		//Create security policy
+		RSqlSecurityPolicy securityPolicy;
+		CleanupClosePushL(securityPolicy);	
+		
+		User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
+		User::LeaveIfError(iDatabase.Create(dbFile, securityPolicy, heapBuf));
+		CleanupStack::PopAndDestroy(); //securityPolicy
+#endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+
+		CleanupStack::PopAndDestroy(); //heapBuf
+		}
+	CleanupStack::PopAndDestroy(); //dbFile
+			
+	//Construct the data structure to store maximum TMsvIds in
+	//a given driveId.
+	iDatabasePresent = new(ELeave)RArray<TBool>(KMaxNumberOfDrives);
+	//Initialisation.
+	for(TInt index = 0; index < KMaxNumberOfDrives; ++index)
+		{
+		iDatabasePresent->Append(EFalse);
+		}
+	
+	}
+	
+
+
+
+/**
+ * AttachDBL()
+ * @param TDriveUnit The drive information of the drive to be checked.
+ * @param TUint The driveId of the drive (0-7).
+ * @param TMsvId& An output parameter that gives the maximum TMsvId of an 
+ *				  entry in the messaging database of that drive.
+ * 
+ * Attaches a database on the specified drive to the main (dummy) 
+ * database on the system drive so that appropriate queries 
+ * access entries in that database too. The function calls MaxTMsvIdL()
+ * to query the particular database to get the maximum TMsvId of an entry 
+ * stored in it. This TMsvId is maintained in a data structure which has 
+ * the driveId as the index.
+ *
+ * The database is detached by using its logical name which can
+ * be obtained from the driveId.
+ * (E.g.: logical name of a database on driveId 3 is 'DB3'. A query on the
+ * IndexEntry in this database should address the table as DB3.IndexEntry.)
+ */
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+void CMsvDBAdapter::AttachDBL(TDriveUnit aDriveUnit, TUint aDriveId, TMsvId& aMaxId, CMsvMessageDBAdapter* iMessageDBAdapter/*default= NULL*/)
+#else
+void CMsvDBAdapter::AttachDBL(TDriveUnit aDriveUnit, TUint aDriveId, TMsvId& aMaxId)
+#endif
+	{
+	//Construct the logical name of the database to be attached from 
+	//the driveId.
+	RBuf logicalName;
+	CleanupClosePushL(logicalName);
+	logicalName.CreateL(5);	
+	logicalName.Append(KLogicalName);
+	logicalName.AppendNum(aDriveId);
+		
+	//Construct the DB filename appending messaging DB name to the drive name.
+	RBuf dbFile;
+	CleanupClosePushL(dbFile);
+	dbFile.CreateL(50);	
+	dbFile.Append(aDriveUnit.Name());
+	dbFile.Append(KMessagingDBName);
+	
+	//Attach the database to the connection.
+	User::LeaveIfError(iDatabase.Attach(dbFile, logicalName));
+	
+	//Find the parameter and column indexes just once.
+	if((KErrNotFound == iDatabasePresent->Find(ETrue)) && (!iDbPtrInitialized))
+		{
+		InitializeL();
+		iDbPtrInitialized = ETrue;
+		}
+		
+	//Find the maximum TMsvId in the database and store it.
+	aMaxId = MaxTMsvIdL(aDriveId);
+	(*iDatabasePresent)[aDriveId] = ETrue;
+	
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	if(iMessageDBAdapter)
+		{
+		iMessageDBAdapter->UpdateMetadataStructureL(aDriveId);		
+		}	
+#endif
+
+	CleanupStack::PopAndDestroy(2); //logicalName, dbFile	
+	}
+
+	
+
+	
+/**
+ * DetachDBL()
+ * @param TUint The driveId (0-7) of the drive from which the database
+ * 				is to be detached.
+ * @return None.
+ *
+ * Detaches a database on the drive specified by the driveId from
+ * the main database connection. This is done when:
+ * a. The disk is removed from the drive.
+ * b. The drive is removed from the preferred drive list.
+ *
+ * The database is detached by using its logical name which can
+ * be obtained from the driveId.
+ * (E.g.: logical name of a database on driveId 3 is 'DB3'.)
+ */
+void CMsvDBAdapter::DetachDBL(TUint aDriveId)
+	{
+	//Construct the logical name.
+	RBuf logicalName;
+	CleanupClosePushL(logicalName);
+	logicalName.CreateL(5);	
+	logicalName.Append(KLogicalName);
+	logicalName.AppendNum(aDriveId);
+	
+	User::LeaveIfError(iDatabase.Detach(logicalName));
+	
+	CleanupStack::PopAndDestroy(); //logicalName
+	
+	(*iDatabasePresent)[aDriveId] = EFalse;
+	
+	}
+
+
+
+
+/**
+ * CreateDBL()
+ * @param TDriveNumber The drive number of the drive on which a 
+ *						a new messaging database is to be created.
+ * @return None.
+ *
+ * Creates the messaging database on the drive specified by the TDriveNumber
+ * using a temporary local database connection.
+ * Also creates the IndexEntry table and an index on the parentId field in it,
+ * and then the Root entry in the database.
+ * Also creates a version table, which is a database with just one column
+ * and row which stores the current database version for message store
+ * versioning.
+ */
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+void CMsvDBAdapter::CreateDBL(TDriveNumber aDriveNumber, TBool aCreateVersionTable /*Default=ETrue*/, TBool aInvalid /*Default=EFalse*/)
+#else
+void CMsvDBAdapter::CreateDBL(TDriveNumber aDriveNumber)
+#endif
+	{
+	//Construct the database filename.
+	TParse parse;
+	TPtrC drive = TDriveUnit(aDriveNumber).Name();
+	parse.Set(KMessagingDBName, &drive, NULL);
+	TFileName dbFileName = parse.FullName();
+	
+	RSqlDatabase tempDB; //A temporary local database connection.
+	CleanupClosePushL(tempDB);
+
+	HBufC8* heapBuf = KEncodingText().AllocLC();
+
+	//Create the database.
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	User::LeaveIfError(tempDB.Create(dbFileName, heapBuf));
+#else	
+	// Using SID based security policy.
+	TSecureId sid(SERVER_UID);
+	const TSecurityPolicy KDefaultPolicy(sid);
+	
+	//Create security policy
+	RSqlSecurityPolicy securityPolicy;
+	CleanupClosePushL(securityPolicy);	
+		
+	User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
+	User::LeaveIfError(tempDB.Create(dbFileName, securityPolicy, heapBuf));
+	
+	CleanupStack::PopAndDestroy(); //securityPolicy
+#endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+
+	CleanupStack::PopAndDestroy(); //heapBuf
+	
+	//Create tables for the database
+	TInt err = tempDB.Exec(KCreateIndexEntryTableQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+		
+	//Create index on indexEnty table.
+	//Index is created on parentId.
+	err = tempDB.Exec(KCreateIndexQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	
+	// Create root entry in DB.
+	CreateRootEntryL(tempDB);	
+
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	if(aCreateVersionTable)
+		{
+#endif
+	//Create the version table to store the message store version.
+	err = tempDB.Exec(KCreateVersionTableQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	//Insert the version number into the above table.
+	_LIT(KInsertVersionNumberQuery, " INSERT INTO VersionTable Values ( " );
+	RBuf8 versionQuery;
+	CleanupClosePushL(versionQuery);
+	versionQuery.CreateL(50);
+	versionQuery.Append(KInsertVersionNumberQuery);
+
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	if(aInvalid) //create an invalid database wrt version for testing
+		versionQuery.AppendNum(999);
+	else
+		versionQuery.AppendNum(KCurrentDatabaseVersion);	
+#else
+	versionQuery.AppendNum(KCurrentDatabaseVersion);	
+#endif
+
+	versionQuery.Append(_L(");"));
+	err = tempDB.Exec(versionQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+
+	CleanupStack::PopAndDestroy();	//versionQuery
+		
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)		
+		}
+#endif
+	
+	CleanupStack::PopAndDestroy(); // tempDB
+	}
+ 
+ 
+
+/**
+ * CreateRootEntryL()
+ *
+ * Creates root entry in the DB.
+ */
+void CMsvDBAdapter::CreateRootEntryL(RSqlDatabase& tempDB)
+	{
+	_LIT(KCreateRootEntryQuery, "INSERT INTO IndexEntry VALUES (");
+	_LIT(KComma, ", ");
+	_LIT(KDelimiter, " );");
+	
+	TMsvEntry rootEntry;
+	rootEntry.iType = KUidMsvRootEntry;
+	rootEntry.iMtm = KUidMsvRootEntry;
+	rootEntry.iDate.UniversalTime();
+	rootEntry.SetId(KMsvRootIndexEntryId);
+	rootEntry.SetParent(KErrNotFound);
+	rootEntry.SetOwner(ETrue);
+	rootEntry.iSize = 0;
+	
+	RBuf queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(300);	
+	queryBuf.Append(KCreateRootEntryQuery);
+	queryBuf.AppendNum(rootEntry.iId);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.Parent());
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iServiceId);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iMtm.iUid);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iType.iUid);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iDate.Int64());
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iData);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iSize);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iError);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iMtmData1);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iMtmData2);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iMtmData3);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iRelatedId);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iBioType);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iPcSyncCount);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(rootEntry.iReserved);
+	queryBuf.Append(KComma);
+	queryBuf.AppendNum(KMsvRootIndexEntryId);
+	queryBuf.Append(KComma);
+	queryBuf.Append(_L("\"\""));
+	queryBuf.Append(KComma);
+	queryBuf.Append(_L("\"\""));
+	queryBuf.Append(KDelimiter);
+	
+	TInt err = tempDB.Exec(queryBuf);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	CleanupStack::PopAndDestroy(); //queryBuf	
+	}
+	
+	
+	
+
+/**
+ * MaxTMsvIdL()
+ * @param TDriveNumber The drive number of the drive to be queried.
+ * @return None.
+ *
+ * Queries the specified drive's database for the maximum TMsvId
+ * of an entry stored in it.
+ */
+TMsvId CMsvDBAdapter::MaxTMsvIdL(TUint aDriveId)
+	{	 
+	_LIT(KMaxTMsvIdQuery1, "SELECT MAX(id) FROM DB");
+	_LIT(KMaxTMsvIdQuery2, ".IndexEntry;");
+	
+	RBuf queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(50);	
+	
+	queryBuf.Append(KMaxTMsvIdQuery1);
+	queryBuf.AppendNum(aDriveId);
+	queryBuf.Append(KMaxTMsvIdQuery2);
+	
+	//Create a select query
+    TSqlScalarFullSelectQuery query(iDatabase);
+
+	//Get the column data
+    TMsvId maxTMsvId = query.SelectIntL(queryBuf);
+    
+    CleanupStack::PopAndDestroy(); //queryBuf
+    
+    if(KMsvRootIndexEntryId != maxTMsvId)
+    	maxTMsvId = MaskTMsvId(aDriveId, maxTMsvId);
+    return maxTMsvId;
+	}
+
+
+
+
+/**
+ * ValidateDatabaseL()
+ * @param TDriveNumber The drive number of the drive to be checked.
+ * @return None.
+ *
+ * Validates a database by checking if:
+ * a. The database file is in the appropriate location.
+ * b. The database is readable and not corrupt.
+ * c. The database is of latest supported version.
+ * d. All standard folders (as specified in the messaging resource file)
+ *    exist in the database.
+ */
+void CMsvDBAdapter::ValidateDatabaseL(TDriveNumber aDriveNumber)
+	{
+	//Check (a) and (b).
+	TParse parse;
+	TPtrC drive(TDriveUnit(aDriveNumber).Name());
+	parse.Set(KMessagingDBName, &drive, NULL);
+	TFileName dbFile = parse.FullName();
+	
+	RSqlDatabase tempDB;
+	CleanupClosePushL(tempDB);
+	tempDB.OpenL(dbFile);
+		
+	//Check (d) with the connection still open.
+	//Entries to be checked are Root, Local, Inbox, Outbox, Drafts,
+	//Sent and Deleted.
+	_LIT(KStandardEntryExistsQuery1, "SELECT count(*) FROM IndexEntry WHERE id <= ");
+	RBuf queryBuf;	
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(150);
+	queryBuf.Append(KStandardEntryExistsQuery1);
+	queryBuf.AppendNum(KMsvDeletedEntryFolderEntryId);
+	queryBuf.Append(KDelimiter);
+	
+	TSqlScalarFullSelectQuery query(tempDB);
+	TInt folders = 0;
+	folders = query.SelectIntL(queryBuf);
+	
+	//The database is invalid if the number of folders returned
+	//from the above query is not 7.
+	if(folders != KMsvNumStdFolder) //Number of standard folders + root. To be put in a macro or const
+		{
+		User::Leave(KSqlErrCorrupt); 
+		}
+	CleanupStack::PopAndDestroy(); //queryBuf	
+	
+	//(a), (b) and (d) are fine. Check (c).
+	//Check the version number against the expected version number.
+	//PREQ557 version - 1; Post-557 version - 2.
+	_LIT(KSelectVersionQuery, "SELECT version FROM VersionTable;");
+	TInt version = 0;
+	
+	version = query.SelectIntL(KSelectVersionQuery);
+	if(version != KCurrentDatabaseVersion)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	CleanupStack::PopAndDestroy();  // tempDB
+	}
+
+
+
+
+/**
+ * GetVisibleFolderIdL()
+ * @param TMsvId: Parent Id.
+ * @param TMsvId&: Out parameter for most immediate visible folder id of
+ *				   any child entry present under passed parent id.
+ * @return None. 
+ *
+ * This functions returns the most immediate parent visible folder id.
+ * There are two types of folders. A visible folder is one which is 
+ * visible to the external user, but there are internal non-visible folders
+ * created under each email message to organize the content of the email.
+ * Parent entry of an entry is either root or a folder. A folder can be 
+ * service folder (like LocalServices), user-defined folder/standard folder
+ * like Inbox or a non-visible folder (created under an email message).
+ * 
+ * For a given parent Id, the function returns the most immediate visible
+ * parent folder. The rules are as follows:
+ * 1. If the parent entry is root or children of root, then the visibleFolder 
+ * will be root itself. This is because service folders are considered 
+ * invisible, since they are not seen by user. 
+ * 2. If the parent entry itself is a visible folder then child's visibleFolder
+ * id should be its parent id.
+ * 3. If the parent entry is a non-visible folder then child's visibleFolder
+ * id is same as its parent's visibleFolder id.
+ */
+void CMsvDBAdapter::GetVisibleFolderIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
+	{
+	// If the entry is either a root entry (parent=KErrNotFound) or 
+	// child of root entry its visibleFolderId will be root entry itself.
+	if(KErrNotFound == aParentId)
+		{
+		aVisibleFolderId = KMsvRootIndexEntryId;
+		return;		
+		}
+
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aParentId);
+	aParentId = UnmaskTMsvId(aParentId);
+
+	if(KMsvRootIndexEntryId == aParentId)
+		{
+		aVisibleFolderId = KMsvRootIndexEntryId;
+		}
+	else
+		{
+		//Construct a query for the particular drive.
+		_LIT8(KGetVisibleIdQuery1, "SELECT data, visibleParent FROM DB");
+		_LIT8(KGetVisibleIdQuery2, ".IndexEntry WHERE id = ");
+		
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(70);		
+		queryBuf.Append(KGetVisibleIdQuery1);
+		queryBuf.AppendNum(driveId);
+		queryBuf.Append(KGetVisibleIdQuery2);
+		queryBuf.AppendNum(aParentId);
+		queryBuf.Append(KDelimiter);
+		
+		RSqlStatement visQuery;
+		CleanupClosePushL(visQuery);
+		User::LeaveIfError(visQuery.Prepare(iDatabase, queryBuf));
+		TInt dataParam = GetColumnIndexL(visQuery, KMsgColumnData());
+		TInt visParam = GetColumnIndexL(visQuery, KMsgColumnVisibleParent());
+		
+		if (KSqlAtRow != visQuery.Next())
+			{
+			User::Leave(KErrNotFound);
+			}
+		
+		TInt32 data = ColumnInt(visQuery, dataParam);
+		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
+			{
+			// If visible folder flag is not set for parent entry.
+			aVisibleFolderId = ColumnInt(visQuery, visParam);
+			if(!IsStandardId(aVisibleFolderId))
+				{
+				aVisibleFolderId = MaskTMsvId(driveId, aVisibleFolderId);
+				}
+			}
+		else
+			{
+			// If parent entry is visible
+			if(IsStandardId(aParentId))
+				{
+				aVisibleFolderId = aParentId;				
+				}
+			else
+				{
+				aVisibleFolderId = MaskTMsvId(driveId, aParentId);
+				}
+			}		
+		CleanupStack::PopAndDestroy(2); //visQuery, queryBuf
+		}
+	}
+
+
+
+
+/**
+ * CreateEntryL()
+ * @param const TMsvEntry&: The entry to be created.
+ * @param const TMsvId: Immediate visible parent folder of the entry
+ * @return None.
+ *
+ * The function creates a new entry in the database.
+ * No consisitency check is performed on the passed entry. The function may
+ * leave if query execution fails.
+ */
+void CMsvDBAdapter::CreateEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
+	{
+	_LIT8(KCreateEntryQuery1,	 "INSERT INTO DB");
+	_LIT8(KCreateEntryQuery2, ".IndexEntry VALUES ("
+							  ":id, :parentId, :serviceId, :mtmId, :type, :date, :data, :size, :error,"
+							  ":mtmData1, :mtmData2, :mtmData3, :relatedId, :bioType, :pcSyncCount,"
+							  ":reserved, :visibleParent, :description, :details);"
+		 );
+
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aNewEntry.iId);
+	TMsvId id = UnmaskTMsvId(aNewEntry.iId);
+	TMsvId parentId = UnmaskTMsvId(aNewEntry.iParentId);
+	TMsvId visFolder = UnmaskTMsvId(aImmediateVisibleFolder);
+	TMsvId serviceId = UnmaskTMsvId(aNewEntry.iServiceId);
+	TMsvId relatedId = UnmaskTMsvId(aNewEntry.iRelatedId);
+	
+	//Construct a query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(350);
+	queryBuf.Append(KCreateEntryQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KCreateEntryQuery2);
+	iStatement[ECreateEntry].Close(); //closing any statement prepared previously
+	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, queryBuf));
+	
+	//Bind the entry data
+	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], id);
+	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], parentId);
+	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
+	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
+	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
+	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], relatedId);
+	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
+	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
+	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
+	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
+	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
+	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
+	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
+	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
+	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], serviceId);
+	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
+	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], visFolder);
+	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
+	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
+	
+	TInt err = iStatement[ECreateEntry].Exec();
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	iStatement[ECreateEntry].Close();
+	CleanupStack::PopAndDestroy();
+	}
+
+
+
+
+/**
+ * UpdateEntryL()
+ * @param const TMsvEntry&: Entry to be updated.
+ * @param const TMsvId: the visible folder Id of the updated entry.
+ * @param TBool: ETrue if the parent of the entry has been changed,
+ *				 EFalse if otherwise.
+ * @return None.
+ *
+ * The function updates an entry in the database.
+ * No consisitency check is performed on the passed entry. The function may
+ * leave if query execution fails.
+ */
+void CMsvDBAdapter::UpdateEntryL(const TMsvEntry& aEntry, const TMsvId aImmediateVisibleFolder, TBool aIsParentIdUpdated/*DEFAULT=ETrue*/)
+	{
+	_LIT8(KUpdateEntryQuery1,	"UPDATE DB");
+	_LIT8(KUpdateEntryQuery2, ".IndexEntry SET ");
+	_LIT8(KUpdateEntryQueryWithParent,	"parentId = :parentId, ");
+	_LIT8(KUpdateEntryQueryWithoutParent,	"serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
+							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
+							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
+							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
+							"details = :details WHERE id = :id;"
+		 );
+	
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aEntry.iId);
+	TMsvId id = UnmaskTMsvId(aEntry.iId);
+	TMsvId parentId = UnmaskTMsvId(aEntry.iParentId);
+	TMsvId serviceId = UnmaskTMsvId(aEntry.iServiceId);
+	TMsvId relatedId = UnmaskTMsvId(aEntry.iRelatedId);
+	TMsvId visFolder = UnmaskTMsvId(aImmediateVisibleFolder);
+	
+	//Form the query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(500);	
+	queryBuf.Append(KUpdateEntryQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KUpdateEntryQuery2);
+
+	iStatementType updateStmt;
+	TInt err = KErrNone;
+	//Bind the entry data
+	if(aIsParentIdUpdated)
+		{
+		updateStmt = EUpdateEntry;
+		queryBuf.Append(KUpdateEntryQueryWithParent);
+		queryBuf.Append(KUpdateEntryQueryWithoutParent);
+		iStatement[updateStmt].Close(); //closing any statement prepared previously
+		User::LeaveIfError(iStatement[updateStmt].Prepare(iDatabase, queryBuf));
+		BindIntL(iStatement[updateStmt], iParentIdIndex[updateStmt], parentId);
+		}
+	else
+		{
+		updateStmt = EUpdateEntryNoParent;
+		iStatement[updateStmt].Close(); //closing any statement prepared previously
+		queryBuf.Append(KUpdateEntryQueryWithoutParent);
+		User::LeaveIfError(iStatement[updateStmt].Prepare(iDatabase, queryBuf));
+		}
+	BindIntL(iStatement[updateStmt], iVisibleParent[updateStmt], visFolder);
+	BindIntL(iStatement[updateStmt], iIdIndex[updateStmt], id);
+	BindIntL(iStatement[updateStmt], iDataIndex[updateStmt], aEntry.iData);
+	BindIntL(iStatement[updateStmt], iPcSyncCountIndex[updateStmt], aEntry.iPcSyncCount);
+	BindIntL(iStatement[updateStmt], iReservedIndex[updateStmt], aEntry.iReserved);
+	BindIntL(iStatement[updateStmt], iRelatedIdIndex[updateStmt], relatedId);
+	BindIntL(iStatement[updateStmt], iTypeIndex[updateStmt], aEntry.iType.iUid);
+	BindInt64L(iStatement[updateStmt], iDateIndex[updateStmt], aEntry.iDate.Int64());
+	BindIntL(iStatement[updateStmt], iSizeIndex[updateStmt], aEntry.iSize);
+	BindIntL(iStatement[updateStmt], iErrorIndex[updateStmt], aEntry.iError);
+	BindIntL(iStatement[updateStmt], iBiotypeIndex[updateStmt], aEntry.iBioType);
+	BindIntL(iStatement[updateStmt], iMtmData1Index[updateStmt], aEntry.iMtmData1);
+	BindIntL(iStatement[updateStmt], iMtmData2Index[updateStmt], aEntry.iMtmData2);
+	BindIntL(iStatement[updateStmt], iMtmData3Index[updateStmt], aEntry.iMtmData3);
+	BindIntL(iStatement[updateStmt], iServiceIdIndex[updateStmt], serviceId);
+	BindIntL(iStatement[updateStmt], iMtmIdIndex[updateStmt], aEntry.iMtm.iUid);
+	BindTextL(iStatement[updateStmt], iDescriptionIndex[updateStmt],aEntry.iDescription);
+	BindTextL(iStatement[updateStmt], iDetailsIndex[updateStmt],aEntry.iDetails);
+
+	//Execute the prepared SQL statement.
+	err = iStatement[updateStmt].Exec();
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	iStatement[updateStmt].Close();
+	CleanupStack::PopAndDestroy(); //queryBuf
+	}
+
+
+
+
+/**
+ * DeleteEntryL()
+ * @param TMsvId: Entry Id to be deleted.
+ *
+ * The function deletes an entry with the passed Id. The function
+ * may leave due to database error while execution. The function
+ * does not leave if the entry does not exist.
+ *
+ * **WARNING** The function does NOT ensure that if a parent entry
+ * is deleted all its child entries are also deleted.
+ */
+void CMsvDBAdapter::DeleteEntryL(TMsvId aEntryId)
+	{
+	_LIT8(KDeleteEntryQuery1, "DELETE FROM DB");
+	_LIT8(KDeleteEntryQuery2, ".IndexEntry WHERE id = ");
+		
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aEntryId);
+	aEntryId = UnmaskTMsvId(aEntryId);
+	
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(100);	
+	queryBuf.Append(KDeleteEntryQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KDeleteEntryQuery2);
+	queryBuf.AppendNum(aEntryId);
+	queryBuf.Append(KDelimiter);
+	
+	TInt err = iDatabase.Exec(queryBuf);
+	CleanupStack::PopAndDestroy();
+	if(err < 0)
+		{		
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrNotFound);			
+		}	
+	}
+
+
+
+
+/**
+ * DeleteEntryL()
+ * @param const CMsvEntrySelection&: Entry Id list to be deleted.
+ * @return None.
+ * 
+ * The function deletes all entries mentioned in the passed Id list.
+ * The function may leave due to database error while execution or
+ * if an entry does not exist.
+ *
+ * **WARNING** The function does NOT ensure that if a parent entry
+ * is deleted all its child entries are also deleted.
+ */
+void CMsvDBAdapter::DeleteEntryL(const CMsvEntrySelection& aEntryIdList)
+	{	
+	TInt count;
+	if( 0 == (count = aEntryIdList.Count()) )
+		{
+		return;
+		}
+
+	_LIT(KQuery1, "DELETE FROM DB");
+	_LIT(KQuery2, ".IndexEntry WHERE id IN (");
+	_LIT(KEndDelimiter, ");");
+	
+	//Delete maximum 100 entries at a time so as to not overflow IPC buffer
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	TInt maxEntries = 50; //for testing
+#else
+	TInt maxEntries = 100;
+#endif
+
+	CMsvEntrySelection* entryList = aEntryIdList.CopyL(); //separate copy of the list to work on
+	CleanupStack::PushL(entryList);
+	
+	for(TInt index1 = 0; index1<count; ++index1)
+		{
+		TInt driveId = GetDriveId(entryList->At(index1));
+		TInt numDeleted = 1;
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(70 + ((10+2)*maxEntries));		
+		queryBuf.Append(KQuery1);
+		queryBuf.AppendNum(driveId);
+		queryBuf.Append(KQuery2);
+		queryBuf.AppendNum(UnmaskTMsvId(entryList->At(index1)));
+		for(TInt index2 = index1 + 1; index2<count && numDeleted<maxEntries; ++index2)
+			{
+			if(driveId == GetDriveId(entryList->At(index2)))
+				{
+				queryBuf.Append(KComma);
+				queryBuf.AppendNum(UnmaskTMsvId(entryList->At(index2)));
+				++numDeleted;
+				entryList->Delete(index2);
+				--index2;
+				--count;
+				}
+			}
+		entryList->Delete(index1);
+		--index1;
+		--count;
+		queryBuf.Append(KEndDelimiter);
+		TInt err = iDatabase.Exec(queryBuf);
+		CleanupStack::PopAndDestroy(); //queryBuf
+		if(err < 0)
+			{
+			User::Leave(err);
+			}
+		}
+	CleanupStack::PopAndDestroy(); //entryList
+	}
+
+
+
+
+/**
+ * GetEntryL()
+ * @param TMsvId: Id of the entry to be fetched.
+ * @param CMsvCacheEntry*&: The newly fetched entry.
+ * @param TMsvId&: Out parameter for value of VisibleParent column.
+ * @return None.
+ *
+ * Fetch an entry from the database. Memory to aEntry
+ * should not already be assigned.
+ */
+void CMsvDBAdapter::GetEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TMsvId& aVisibleParentEntryId)
+	{
+	_LIT8(KGetEntryQuery1, "SELECT parentId, serviceId, mtmId, type, date, data, size, error, "
+						"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+						"reserved, visibleParent, description, details FROM DB");
+	_LIT8(KGetEntryQuery2, ".IndexEntry WHERE id = ");
+
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aId);
+	
+	//Construct a query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	TInt len = KGetEntryQuery1().Length() + KGetEntryQuery2().Length() + 15;
+	queryBuf.CreateL(len);	
+	queryBuf.Append(KGetEntryQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KGetEntryQuery2);
+	queryBuf.AppendNum(UnmaskTMsvId(aId));
+	queryBuf.Append(KDelimiter);
+	
+	//Prepare a statement for the query.
+	RSqlStatement getStmt;
+	CleanupClosePushL(getStmt);
+	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
+		
+	if(KSqlAtRow != getStmt.Next())
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	//Get the entry from the statement
+	aEntry = CMsvEntryFreePool::Instance()->EntryL();
+	aEntry->Entry().iId = aId;
+	
+	LoadEntryFromStatementL(getStmt, EGetEntry, aVisibleParentEntryId, *aEntry);
+	
+	//We do not return non-standard visible folders from a non-current drive's database.
+	if(driveId != KCurrentDriveId 		&&
+	   aEntry->Entry().Visible() 		&&
+	   !IsStandardId(aEntry->GetId()) 	&&
+	   KUidMsvFolderEntryValue == aEntry->Entry().iType.iUid
+	  )
+		{
+		CMsvEntryFreePool::Instance()->ReleaseEntry(aEntry);
+		User::Leave(KErrNotFound);
+		}
+	
+	// Unmask iId's of standard Ids.
+	if(IsStandardId(aEntry->GetId()))
+		{
+		aEntry->Entry().SetId(UnmaskTMsvId(aEntry->GetId()));
+		}
+	
+	// Mask iParentId if it is a non-standard id.
+	if(!IsStandardId(aEntry->Entry().iParentId))
+		{
+		aEntry->Entry().iParentId = MaskTMsvId(driveId, aEntry->Entry().iParentId);
+		}
+	
+	// Mask visible folder if it is a non-standard id.
+	if(!IsStandardId(aVisibleParentEntryId))
+		{
+		aVisibleParentEntryId = MaskTMsvId(driveId, aVisibleParentEntryId);
+		}
+	
+	// Mask iServiceId if it is a non-standard id.
+	if(!IsStandardId(aEntry->Entry().iServiceId))
+		{
+		aEntry->Entry().iServiceId = MaskTMsvId(driveId, aEntry->Entry().iServiceId);
+		}
+	
+	// Mask iRelatedId if it is a non-standard id.
+	if(!IsStandardId(aEntry->Entry().iRelatedId))
+		{
+		aEntry->Entry().iRelatedId = MaskTMsvId(driveId, aEntry->Entry().iRelatedId);
+		}
+	
+	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
+	}
+
+
+
+
+/**
+ * GetChildrenL()
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
+ * @return None.
+ *
+ * Fetch child entries from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
+	{
+	_LIT8(KGetChildEntriesQuery1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
+							"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+							"reserved, visibleParent, description, details FROM DB");
+	_LIT8(KGetChildEntriesQuery2, ".IndexEntry WHERE parentId = ");
+	_LIT8(KGetChildEntriesQuery3, " order by id ASC;");
+	
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aParentId);
+	aParentId = UnmaskTMsvId(aParentId);
+	
+	//Construct the query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(350);	
+	queryBuf.Append(KGetChildEntriesQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KGetChildEntriesQuery2);
+	queryBuf.AppendNum(aParentId);
+	queryBuf.Append(KGetChildEntriesQuery3);
+	
+	//Prepare a statement for the query.
+	RSqlStatement getStmt;
+	CleanupClosePushL(getStmt);
+	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
+	
+	while(KSqlAtRow == getStmt.Next())
+		{
+		// Do not return non-standard visible folders from non-current drive.
+			// If it is a non-current drive...
+		if( (driveId != KCurrentDriveId) 										     	  &&
+			// If it is a folder entry.
+		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildEntries])) &&
+		    // If it is a visible folder.
+			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildEntries])))		      &&
+			// If it is a non-standard folder.
+			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildEntries])))
+		  )		  		
+			{
+			continue;
+			}
+			
+		TMsvId aVisibleParentEntryId;
+		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
+		if(!IsStandardId(aParentId))
+			{
+			aParentId = MaskTMsvId(driveId, aParentId);
+			}
+		cacheEntry->Entry().iParentId = aParentId;
+		LoadEntryFromStatementL(getStmt, EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
+		
+		//Add the drive mask to the TMsvId.
+		if(!IsStandardId(cacheEntry->GetId()))
+			{
+			cacheEntry->Entry().iId = MaskTMsvId(driveId, cacheEntry->Entry().iId);
+			}
+		
+		// Mask iServiceId if it is a non-standard id.
+		if(!IsStandardId(cacheEntry->Entry().iServiceId))
+			{
+			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
+			}
+		
+		// Mask iRelatedId if it is a non-standard id.
+		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
+			{
+			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
+			}
+	
+		//Add the child entry to the array given
+		aChildArray.AppendL(cacheEntry);
+		}
+	
+	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
+	}
+
+
+
+
+/**
+ * GetChildrenIdL()
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @param CMsvEntrySelection&: List of child entry Id's.
+ * @return None.
+ *
+ * Fetch child entry Id's from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
+	{
+	_LIT8(KGetChildIdsQuery1, "SELECT id, type, data FROM DB");
+	_LIT8(KGetChildIdsQuery2, ".IndexEntry WHERE parentId = ");
+	_LIT8(KGetChildIdsQuery3, " order by id ASC;");
+	
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aParentId);
+	aParentId = UnmaskTMsvId(aParentId);
+	
+	//Construct the query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(100);	
+	queryBuf.Append(KGetChildIdsQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KGetChildIdsQuery2);
+	queryBuf.AppendNum(aParentId);
+	queryBuf.Append(KGetChildIdsQuery3);
+	
+	//Prepare a statement for the query.
+	RSqlStatement getStmt;
+	CleanupClosePushL(getStmt);
+	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
+	
+	while(KSqlAtRow == getStmt.Next())
+		{
+		// Do not return non-standard visible folders from non-current drive.
+			// If it is a non-current drive...
+		if( (driveId != KCurrentDriveId) 					 				     	  &&
+			// If it is a folder entry.
+		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildIds])) &&
+		    // If it is a visible folder.
+			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildIds])))		      &&
+			// If it is a non-standard folder.
+			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildIds])))
+		  )		  		
+			{
+			continue;
+			}
+		
+		TMsvId id = ColumnInt(getStmt, iIdIndex[EGetChildIds]);
+		if(!IsStandardId(id))
+			{
+			id = MaskTMsvId(driveId, id);
+			}
+		//Add the child Id to the array given
+		aChildArray.AppendL(id);
+		}
+	
+	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
+	}
+
+
+
+
+/**
+ * GetChildrenL()
+* @param const TDesC&: Partial query string. (Where clause condition).
+ *               The query string should start with 'AND' and should 
+ *               end with a semicolon. Examples are:
+ *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
+ * @return None.
+ *
+ * Fetch child entries from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
+	{
+	_LIT8(KQueryString1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
+			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+			"reserved, visibleParent, description, details FROM DB");
+	_LIT8(KQueryString2, ".IndexEntry WHERE parentId = ");
+
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aParentId);
+	aParentId = UnmaskTMsvId(aParentId);
+	
+	//Construct a query for the particular drive.
+	TInt len = KQueryString1().Length() + KQueryString2().Length() + aQueryStr.Length();
+	len += 30;
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(len);	
+	queryBuf.Append(KQueryString1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KQueryString2);
+	queryBuf.AppendNum(aParentId);
+	queryBuf.Append(aQueryStr);
+	
+	//Prepare a statement for the query.
+	RSqlStatement condGetChildrenStmnt;
+	CleanupClosePushL(condGetChildrenStmnt);
+	
+	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
+	TInt index = 0;
+
+	while(KSqlAtRow == condGetChildrenStmnt.Next())
+		{
+		TInt type = ColumnInt(condGetChildrenStmnt, 3);
+		TInt32 data = ColumnInt(condGetChildrenStmnt, 5);
+
+		// Do not return non-standard visible folders from non-current drive.
+			// If it is a non-current drive...
+		if( (driveId != KCurrentDriveId) 	  &&
+			// If it is a folder entry.
+		    (KUidMsvFolderEntryValue == type) &&
+		    // If it is a visible folder.
+			(IsVisibleFolder(data))		      &&
+			// If it is a non-standard folder.
+			(!IsStandardId(ColumnInt(condGetChildrenStmnt, 0)))
+		  )
+		  	{
+			continue;
+			}
+		
+		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
+		if(!IsStandardId(aParentId))
+			{
+			aParentId = MaskTMsvId(driveId, aParentId);
+			}
+		cacheEntry->Entry().iParentId = aParentId;
+
+		index = 0;
+		TMsvId id = ColumnInt(condGetChildrenStmnt, index);
+		if(IsStandardId(id))
+			{
+			cacheEntry->Entry().iId = id;
+			}
+		else
+			{
+			cacheEntry->Entry().iId = MaskTMsvId(driveId, id);
+			}		
+		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iType.iUid = type;
+		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iData = data;
+		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
+		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
+		
+		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
+		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
+		
+		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
+		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
+		
+		
+		// Mask iServiceId if it is a non-standard id.
+		if(!IsStandardId(cacheEntry->Entry().iServiceId))
+			{
+			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
+			}
+		
+		// Mask iRelatedId if it is a non-standard id.
+		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
+			{
+			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
+			}
+		
+		//Add the child entry to the array given
+		aChildArray.AppendL(cacheEntry);
+		}
+	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
+	}
+
+
+
+
+/**
+ * EntryExistsL()
+ * @param TMsvId: Entry Id to check.
+ * @return TBool: ETrue if the entry exists, otherwise EFalse.
+ *
+ * Checks if an entry with the specified TMsvId exists in the database.
+ */
+TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
+	{
+	_LIT8(KEntryExistsQuery1, "SELECT id FROM DB");
+	_LIT8(KEntryExistsQuery2, ".IndexEntry WHERE id = ");
+		
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aId);
+	aId = UnmaskTMsvId(aId);
+	
+	//Construct a query for the particular drive.
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	TInt len = KEntryExistsQuery1().Length() + 10 + KEntryExistsQuery2().Length(); //10 = space for TMsvId
+	queryBuf.CreateL(len);	
+	queryBuf.Append(KEntryExistsQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KEntryExistsQuery2);
+	queryBuf.AppendNum(aId);
+	queryBuf.Append(KDelimiter);
+	
+	TSqlScalarFullSelectQuery query(iDatabase);
+	TMsvId id = NULL;
+	TRAPD(err, id = query.SelectIntL(queryBuf));
+	
+	CleanupStack::PopAndDestroy(); //queryBuf
+	if(err!= KErrNone && err!= KErrNotFound)
+		{
+		User::Leave(err);
+		}
+	if(id)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+
+
+	
+/**
+ * GetInPreparationIdL()
+ * @param CMsvEntrySelection&: List of the TMsvEntries 
+ * 		                       whose KMsvEntryInPreparationFlag is set.
+ * @return None.
+ *
+ * Gets the TMsvId's of all the entries whose KMsvEntryInPreparationFlag
+ * is set in the database.
+ */
+void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId /* DEFAULT = 0 */)
+	{
+	if(aDriveId)
+		{
+		DoGetInPreparationIdL(aSelection, aDriveId);
+		}
+	else
+		{
+		//Iterate through all the dives that might have a database.
+		for(TInt driveId = 1; driveId < KMaxNumberOfDrives; ++driveId)
+			{
+			DoGetInPreparationIdL(aSelection, driveId);		
+			}
+		}	
+	}
+
+
+
+
+void CMsvDBAdapter::DoGetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId)
+	{
+	_LIT8(KGetInPreparationIdQuery1, "SELECT id, data FROM DB");
+	_LIT8(KGetInPreparationIdQuery2, ".IndexEntry;");
+	
+	TInt paramIdColumn = 0;
+	TInt paramDataColumn = 1;
+			
+	//Check if the drive has the database present.
+	//The iDatabasePresent array will have a value for only those driveIds which
+	//have been added through AttachDBL().
+	if((*iDatabasePresent)[aDriveId])
+		{
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(40);		
+		queryBuf.Append(KGetInPreparationIdQuery1);
+		queryBuf.AppendNum(aDriveId);
+		queryBuf.Append(KGetInPreparationIdQuery2);
+		
+		RSqlStatement statement;
+		CleanupClosePushL(statement);
+		User::LeaveIfError(statement.Prepare(iDatabase, queryBuf));
+		
+		TMsvId id;
+		TInt32 data;
+		while (KSqlAtRow == statement.Next())
+			{
+			data = ColumnInt(statement, paramDataColumn);
+			if( data & TMsvEntry::KMsvEntryInPreparationFlag )
+				{
+				id = ColumnInt(statement, paramIdColumn);
+				if(!IsStandardId(id))
+					{
+					id = MaskTMsvId(aDriveId, id);
+					}
+				aSelection.AppendL(id);
+				}
+			}
+		CleanupStack::PopAndDestroy(2); //statement, queryBuf
+		}
+	}
+
+	
+	
+
+/**
+ * GetVisibleFlagL()
+ * @param TMsvId: the Id of the entry whose flag is to be checked.
+ * @return TBool: ETrue if the entry is visible, EFalse otherwise.
+ *
+ * Returns the status of the visible flag of an entry in the DB.
+ */
+TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId aEntryId)
+	{
+	_LIT8(KGetVisibleFlagQuery1, "SELECT data FROM DB");
+	_LIT8(KGetVisibleFlagQuery2, ".IndexEntry WHERE id = ");
+	
+	//Get the driveId and unmask the TMsvId supplied.
+	TInt driveId = GetDriveId(aEntryId);
+	aEntryId = UnmaskTMsvId(aEntryId);
+	
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(60);	
+	queryBuf.Append(KGetVisibleFlagQuery1);
+	queryBuf.AppendNum(driveId);
+	queryBuf.Append(KGetVisibleFlagQuery2);
+	queryBuf.AppendNum(aEntryId);
+	queryBuf.Append(KDelimiter);
+	
+	TSqlScalarFullSelectQuery query(iDatabase);
+	TInt32 data = query.SelectIntL(queryBuf);
+	CleanupStack::PopAndDestroy();		// queryBuf
+	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
+		{
+		return EFalse;
+		}
+	else
+		{
+		return ETrue;
+		}
+	}
+
+
+
+
+/**
+ * UpdateVisibleFolderL()
+ * @param CMsvEntrySelection*: List of entries whose visible parent is
+ *							   to be updated.
+ * @param TMsvId: The new visible folder Id.
+ * @return None.
+ *
+ * Updates the visible parent of the entries passed through the selection.
+ */
+ void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* aEntryList, TMsvId aNewVisibleFolderId)
+ 	{
+ 	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE DB");
+ 	_LIT8(KUpdateVisibleFolderQuery2, ".IndexEntry SET visibleParent = ");
+	_LIT8(KUpdateVisibleFolderQuery3,	" WHERE id IN ( ");
+	_LIT8(KEndDelimiter, ");");
+	
+	TInt count = aEntryList->Count();
+	if(0 == count)
+		{
+		return;
+		}
+	
+	//Get the driveId and unmask the TMsvId supplied.
+	aNewVisibleFolderId = UnmaskTMsvId(aNewVisibleFolderId);
+	CMsvEntrySelection* list = aEntryList->CopyL();
+	CleanupStack::PushL(list);
+	
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	TInt maxEntries = 50; //for testing
+#else
+	TInt maxEntries = 100;
+#endif
+	
+	BeginTransactionL();
+	for(TInt index1 = 0; index1<count; ++index1)
+		{
+		TInt driveId = GetDriveId(list->At(index1));
+		
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(50 + ((10+2)*maxEntries));		
+		queryBuf.Append(KUpdateVisibleFolderQuery1);
+		queryBuf.AppendNum(driveId);
+		queryBuf.Append(KUpdateVisibleFolderQuery2);
+		queryBuf.AppendNum(aNewVisibleFolderId);
+		queryBuf.Append(KUpdateVisibleFolderQuery3);
+		queryBuf.AppendNum(UnmaskTMsvId(list->At(index1)));
+		TInt num = 1;
+		for(TInt index2 = index1 + 1; index2<count && num<maxEntries; ++index2)
+			{
+			if(driveId == GetDriveId(list->At(index2)))
+				{
+				queryBuf.Append(KComma);
+				queryBuf.AppendNum(UnmaskTMsvId(list->At(index2)));
+				++num;
+				list->Delete(index2);
+				--index2;
+				--count;
+				}
+			}
+		list->Delete(index1);
+		--index1;
+		--count;
+		queryBuf.Append(KEndDelimiter);
+		TInt err = iDatabase.Exec(queryBuf);
+		CleanupStack::PopAndDestroy(); //queryBuf
+		if(err < 0)
+			{
+			User::Leave(err);
+			}
+		}
+	
+	CommitTransactionL();
+	CleanupStack::PopAndDestroy(); //list
+	}
+
+
+
+
+/**
+ * UpdateOwnerStatusL()
+ *
+ * @param TMsvId: the Id of an entry which has had a child added
+ *				   under it and needs its owner flag updated.
+ * @param const TMsvEntry&: the parent entry.
+ * @param TBool: ETrue if the owner flag should be set, EFalse if otherwise.
+ * @return None.
+ *
+ * The function updates the owner flag of an entry which has had a
+ * child added or deleted under it.
+ */
+void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
+	{
+	_LIT8(KUpdateOwnershipQuery1,	"UPDATE DB");
+	_LIT8(KUpdateOwnershipQuery2, ".IndexEntry SET data = ");
+	_LIT8(KUpdateOwnershipQuery3,	" WHERE id = ");
+	
+	// Owner flag has already been set. Return to caller.
+	if(aParent.Owner() && aSet)
+		{
+		return;
+		}
+	// Otherwise update the owner flag for the entry in the DB.
+	else
+		{
+		//Get the driveId and unmask the TMsvId supplied.
+		TInt driveId = GetDriveId(aId);
+		TMsvId parentId = UnmaskTMsvId(aId);
+		
+		TInt32 data;
+		if(aSet)
+			{
+			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
+			}
+		else
+			{
+			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
+			}
+		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
+		len += KUpdateOwnershipQuery3().Length() + 100; //data and TMsvId.
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(len);		
+		queryBuf.Append(KUpdateOwnershipQuery1);
+		queryBuf.AppendNum(driveId);
+		queryBuf.Append(KUpdateOwnershipQuery2);
+		queryBuf.AppendNum(data);
+		queryBuf.Append(KUpdateOwnershipQuery3);
+		queryBuf.AppendNum(parentId);
+		queryBuf.Append(KDelimiter);
+		TInt err = iDatabase.Exec(queryBuf);
+		if(err < 0)
+			{
+			User::Leave(err);
+			}
+		CleanupStack::PopAndDestroy(); //queryBuf
+		}
+	}
+
+
+
+
+#else		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+
+
+
+/**
+ * NewL()
+ * @param TFileName: DB File Name.
+ * @return The newly created database adapter object.
+ *
+ * The function creates a new secure database in syslib private folder.
+ * It takes database name as input arg and returns instance of 
+ * DB adpater class.
+ */
+CMsvDBAdapter* CMsvDBAdapter::NewL(const TFileName& aDbFileName)
+	{
+	//Create an messaging DB adaptor object.
+	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
+	CleanupStack::PushL(self);
+	
+	// Create the database.
+	TBool isDBCreated = EFalse;
+	TRAPD(err, self->ConstructNewL(aDbFileName, isDBCreated));
+	if( KErrNone != err )
+		{
+		if( isDBCreated )
+			{
+			DeleteDB(aDbFileName);
+			}
+		User::Leave(err);
+		}
+
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+
+
+
+/**
+ * OpenL()
+ * @param TFileName: DB File Name.
+ * @return The newly created database adapter object.
+ *
+ * The function opens an already existing database. The database file
+ * is searched in syslib private folder. It takes database name as 
+ * input arg and returns instance of DB adpater class. The function
+ * leaves if the DB file is not found or if the file is corrupted.
+ */
+CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
+	{
+	//Create an messaging DB adaptor object 
+	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
+	CleanupStack::PushL(self);
+	
+	// Open the database.
+	self->ConstructOpenL(aDbFileName);
+	
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+
+
+
+/**
+ * DeleteDB()
+ * @param TFileName: DB File Name.
+ * @return error.
+ *
+ * This is a static function, hence can be called without creating
+ * an instance of this class. The function deletes the database
+ * file as mentioned in the input argument. The database file is
+ * searched in syslib private folder. 
+ */
+TInt CMsvDBAdapter::DeleteDB(const TFileName& aDbFileName)
+	{
+	return RSqlDatabase::Delete(aDbFileName);
+	}
+
+
+
+
+/**
+ * ConstructOpenL()
+ * @param TFileName: DB File Name.
+ * 
+ * This functions is called by OpenL() to open an existing database.
+ * The function leaves if there is an error while opening the DB with
+ * the leave code same as error code. It takes DB filename as input 
+ * argument. The database file is searched in syslib private folder. 
+ */
+void CMsvDBAdapter::ConstructOpenL(const TFileName& aDbFileName)
+	{
+	// >>> Pass configuration parameter, while opening the DB.
+	User::LeaveIfError(iDatabase.Open(aDbFileName));
+	ClearDBContentsL();
+	ConstructSortTableL();
+	
+	//Initialize the database adapter class
+	InitializeL();
+
+	//Initialize the Search Sort database adapter class
+	InitializeSortTableL();
+	}
+
+
+
+
+/**
+ * ConstructNewL()
+ * @param TFileName: DB File Name.
+ * 
+ * This functions is called by NewL() to create a new database.
+ * The function leaves if there is an error while creating the DB with
+ * the leave code same as error code. It takes DB filename as input 
+ * argument. The database file is created in syslib private folder. 
+ * It then create standard tables as well as indexes in the database.
+ */
+void CMsvDBAdapter::ConstructNewL(const TFileName& aDbFileName, TBool& aIsDBCreated)
+	{
+	HBufC8* heapBuf = KEncodingText().AllocLC();
+
+	//Create the database.
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+	User::LeaveIfError(iDatabase.Create(aDbFileName, heapBuf));
+#else	
+	// Using SID based security policy.
+	TSecureId sid(SERVER_UID);
+	const TSecurityPolicy KDefaultPolicy(sid);
+	
+	//Create security policy
+	RSqlSecurityPolicy securityPolicy;
+	CleanupClosePushL(securityPolicy);	
+		
+	User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
+	User::LeaveIfError(iDatabase.Create(aDbFileName, securityPolicy, heapBuf));
+	
+	// Destroy securityPolicy.
+	CleanupStack::PopAndDestroy();		
+#endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+
+	// Destroy heapBuf
+	CleanupStack::PopAndDestroy();
+	aIsDBCreated = ETrue;
+
+	//Create tables for the database
+	TInt err = iDatabase.Exec(KCreateIndexEntryTableQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+		
+	//Create index on indexEnty table.
+	//Index is created on parentId.
+	err = iDatabase.Exec(KCreateIndexQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	
+	//Create the version table to store the message store version.
+	err = iDatabase.Exec(KCreateVersionTableQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	//Insert the version number into the above table.
+	_LIT8(KInsertVersionNumberQuery, " INSERT INTO VersionTable Values ( " );
+	_LIT8(KDelimiter, " );");
+	RBuf8 versionQuery;
+	CleanupClosePushL(versionQuery);
+	versionQuery.CreateL(50); //a small value is more than enough for the above query.	
+	versionQuery.Append(KInsertVersionNumberQuery);
+	versionQuery.AppendNum(KCurrentDatabaseVersion);
+	versionQuery.Append(KDelimiter);
+	err = iDatabase.Exec(versionQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	CleanupStack::PopAndDestroy(); //versionQuery
+
+	ConstructSortTableL();
+	
+	//Initialize the database adapter class
+	InitializeL();
+
+	//Initialize the Search Sort database adapter class
+	InitializeSortTableL();
+	}
+
+
+
+
+/**
+ * GetVisibleFolderIdL()
+ * @param TMsvId: Parent Id.
+ * @return Most immediate visible folder id of any child entry 
+ *         present under passed parent id.
+ *
+ * This functions returns the most immediate parent visible folder id.
+ * There are two types of folders. A visible folder is one which is 
+ * visible to the external user, but there are internal non-visible folders
+ * created under each email message to organize the content of the email.
+ * Parent entry of an entry is either root or a folder. A folder can be 
+ * service folder (like LocalServices), userdefined folder/standard folder
+ * like Inbox or a non-visible folder (created under an email message).
+ * 
+ * For a given parent Id, the function returns the most immediate visible
+ * parent folder. The rules are as follows:
+ * 1. If the parent entry is root or children of root, then the visibleFolder 
+ * will be root itself. This is because service folders are considered 
+ * invisible, since they are not seen by user. 
+ * 2. If the parent entry itself is a visible folder then child's visibleFolder
+ * id should be its parent id.
+ * 3. If the parent entry is a non-visible folder then child's visibleFolder
+ * id is same as its parent's visibleFolder id.
+ */
+void CMsvDBAdapter::GetVisibleFolderIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
+	{
+	// If the entry is either a root entry (parent=KErrNotFound) or 
+	// child of root entry its visibleFolderId will be root entry itself.
+	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
+		{
+		aVisibleFolderId = KMsvRootIndexEntryId;
+		}
+	else
+		{
+		// Get the visible flag of parent entry.
+		
+		// If parent entry is visible, then immediateVisibleFolder of child
+		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
+		// should be same as parent's immediateVisibleFolder.
+		
+		//Bind the msv id
+		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
+
+		// If parent entry does not exists leave with KErrNotFound.
+		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
+			{
+			iStatement[EGetVisibleId].Reset();
+			User::Leave(KErrNotFound);
+			}
+
+		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
+		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
+			{
+			// If visible folder flag is not set for parent entry.
+			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
+			}
+		else
+			{
+			// If parent entry is visible
+			aVisibleFolderId = aParentId;
+			}
+		//Reset the RSqlStatement
+		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
+		}
+	}
+
+
+
+
+/**
+ * CreateEntryL()
+ * @param const TMsvEntry&: DB File Name.
+ * @return TMsvId: Immediate visible parent folder of the entry
+ *
+ * The function creates a new entry in the database. It gets the immediate
+ * visible folder id of the entry before inserting them into the database.
+ * No consisitency check is performed on the passed entry. The function may
+ * leave if query execution fails.
+ */
+void CMsvDBAdapter::CreateEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
+	{
+	//Bind the entry data
+	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
+	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
+	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
+	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
+	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
+	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
+	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
+	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
+	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
+	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
+	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
+	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
+	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
+	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
+	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
+	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
+	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
+	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
+	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
+	//Execute the prepared SQL statement.
+	
+	TInt err = iStatement[ECreateEntry].Exec();
+	if(err < 0)
+		{
+		iStatement[ECreateEntry].Reset();
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		iStatement[ECreateEntry].Reset();
+		User::Leave(KErrGeneral);
+		}
+	
+	//Reset the RSqlStatement
+	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
+	}
+
+
+
+
+/**
+ * UpdateEntryL()
+ * @param const TMsvEntry&: Entry to be updated.
+ * @param TBool: ETrue if the parent of the entry has been changed,
+ *				 EFalse if otherwise.
+ * @param TMsvId&: the visible folder Id of the updated entry.
+ *				   If aParentChanged is ETrue then aImmediateVisibleFolder
+ *                 is an output parameter, and input parameter if otherwise.
+ * @return None.
+ *
+ * The function updates an entry in the database. It gets the immediate
+ * visible folder id of the entry before inserting them into the database.
+ * No consisitency check is performed on the passed entry. The function may
+ * leave if query execution fails.
+ */
+void CMsvDBAdapter::UpdateEntryL(const TMsvEntry& aEntry, const TMsvId aImmediateVisibleFolder, const TBool aIsParentIdUpdated/*DEFAULT=ETrue*/)
+	{
+	iStatementType updateStmt;
+	//Bind the entry data
+	if(aIsParentIdUpdated)
+		{
+		updateStmt = EUpdateEntry;
+		BindIntL(iStatement[updateStmt], iParentIdIndex[updateStmt], aEntry.iParentId);
+		BindIntL(iStatement[updateStmt], iVisibleParent[updateStmt], aImmediateVisibleFolder);
+		}
+	else
+		{
+		updateStmt = EUpdateEntryNoParent;
+		}
+	BindIntL(iStatement[updateStmt], iIdIndex[updateStmt], aEntry.iId);
+	BindIntL(iStatement[updateStmt], iDataIndex[updateStmt], aEntry.iData);
+	BindIntL(iStatement[updateStmt], iPcSyncCountIndex[updateStmt], aEntry.iPcSyncCount);
+	BindIntL(iStatement[updateStmt], iReservedIndex[updateStmt], aEntry.iReserved);
+	BindIntL(iStatement[updateStmt], iRelatedIdIndex[updateStmt], aEntry.iRelatedId);
+	BindIntL(iStatement[updateStmt], iTypeIndex[updateStmt], aEntry.iType.iUid);
+	BindInt64L(iStatement[updateStmt], iDateIndex[updateStmt], aEntry.iDate.Int64());
+	BindIntL(iStatement[updateStmt], iSizeIndex[updateStmt], aEntry.iSize);
+	BindIntL(iStatement[updateStmt], iErrorIndex[updateStmt], aEntry.iError);
+	BindIntL(iStatement[updateStmt], iBiotypeIndex[updateStmt], aEntry.iBioType);
+	BindIntL(iStatement[updateStmt], iMtmData1Index[updateStmt], aEntry.iMtmData1);
+	BindIntL(iStatement[updateStmt], iMtmData2Index[updateStmt], aEntry.iMtmData2);
+	BindIntL(iStatement[updateStmt], iMtmData3Index[updateStmt], aEntry.iMtmData3);
+	BindIntL(iStatement[updateStmt], iServiceIdIndex[updateStmt], aEntry.iServiceId);
+	BindIntL(iStatement[updateStmt], iMtmIdIndex[updateStmt], aEntry.iMtm.iUid);
+	BindTextL(iStatement[updateStmt], iDescriptionIndex[updateStmt],aEntry.iDescription);
+	BindTextL(iStatement[updateStmt], iDetailsIndex[updateStmt],aEntry.iDetails);
+
+	//Execute the prepared SQL statement.
+	TInt err = iStatement[updateStmt].Exec();
+	if(err < 0)
+		{
+		iStatement[updateStmt].Reset();
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		iStatement[updateStmt].Reset();
+		User::Leave(KErrNotFound);
+		}
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iStatement[updateStmt].Reset());
+	}
+
+
+
+
+/**
+ * DeleteEntryL()
+ * @param TMsvId: Entry Id to be deleted.
+ *
+ * The function deletes an entry with the passed Id. The function
+ * may leave due to database error while execution. The function
+ * does not leave if the entry does not exist.
+ *
+ * **WARNING** The function does NOT ensure that if a parent entry
+ * is deleted all its child entries are also deleted.
+ */
+void CMsvDBAdapter::DeleteEntryL(TMsvId aEntryId)
+	{
+	_LIT8(KDeleteEntryQuery, "DELETE FROM IndexEntry WHERE id = ");
+	_LIT8(KSemiColon, ";");
+	
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(KDeleteEntryQuery().Length() + 20);
+	queryBuf.Append(KDeleteEntryQuery);
+	queryBuf.AppendNum(aEntryId);
+	queryBuf.Append(KSemiColon);
+	
+	TInt err = iDatabase.Exec(queryBuf);
+	if(err < 0)
+		{		
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrNotFound);			
+		}
+	CleanupStack::PopAndDestroy();		// queryBuf
+	}
+
+
+
+
+/**
+ * DeleteEntryL()
+ * @param CMsvEntrySelection: Entry Id list to be deleted.
+ *
+ * The function deletes all entries mentioned in the passed Id list.
+ * The function may leave due to database error while execution or
+ * if an entry does not exist.
+ *
+ * **WARNING** The function does NOT ensure that if a parent entry
+ * is deleted all its child entries are also deleted.
+ */
+void CMsvDBAdapter::DeleteEntryL(const CMsvEntrySelection& aEntryIdList)
+	{
+	TInt count;
+	if( 0 == (count = aEntryIdList.Count()) )
+		{
+		return;
+		}
+
+	_LIT(KQuery, "DELETE FROM IndexEntry WHERE id IN (");
+	_LIT(KComma, ", ");
+	_LIT(KEndDelimeter, ");");
+	
+	RBuf8 buf;
+	CleanupClosePushL(buf);
+	TInt index = 0;
+	//Delete maximum 100 entries at a time so as to not overflow IPC buffer
+	TInt maxEntries = 100;
+	TInt iterRequired = count/maxEntries;
+	if(count%maxEntries)
+		{
+		iterRequired++;
+		}
+	if(iterRequired) 
+		{
+		maxEntries = count/iterRequired;
+		}
+	for(TInt iter = 0; iter < iterRequired; ++iter)
+		{
+		if(iter && iter+1 == iterRequired)
+			{
+			maxEntries = count - index;
+			}		
+		buf.CreateL( 40 + ((7 + 2) * maxEntries) + 2); //KQuery + (TMsvId+KComma)*100 + KEndDelimiter		
+		buf.Append(KQuery);
+		TBool firstId = ETrue;
+		TInt num = 0;
+		while(num < maxEntries)
+			{
+			if(!firstId)
+				{
+				buf.Append(KComma);
+				}
+			firstId = EFalse;
+			buf.AppendNum(aEntryIdList.At(index));
+			++index;
+			++num;
+			}
+		buf.Append(KEndDelimeter);
+		User::LeaveIfError(iDatabase.Exec(buf));		
+		buf.Close();
+		}
+	CleanupStack::PopAndDestroy(); //buf
+	}
+
+
+
+
+/**
+ * GetEntryL()
+ * @param TMsvId: Id of the entry to be fetched.
+ * @return TMsvId: Value of VisibleParent column.
+ * @return TMsvEntry*: The newly fetched entry.
+ *
+ * Fetch an entry from the database. Memory to aEntry
+ * should not already be assigned.
+ */
+void CMsvDBAdapter::GetEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TMsvId& aVisibleParentEntryId)
+	{
+	//Bind the msv id of the entry to be retrieved
+	BindIntL(iStatement[EGetEntry], iIdIndex[EGetEntry], aId);
+
+	if (KSqlAtRow != iStatement[EGetEntry].Next())
+		{
+		iStatement[EGetEntry].Reset();
+		User::Leave(KErrNotFound);
+		}
+
+	//Get the entry from the statement
+	aEntry = CMsvEntryFreePool::Instance()->EntryL();
+	aEntry->Entry().iId = aId;
+	LoadEntryFromStatementL(iStatement[EGetEntry], EGetEntry, aVisibleParentEntryId, *aEntry);
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iStatement[EGetEntry].Reset());
+	}
+
+
+
+
+/**
+ * GetChildrenL()
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @return RPointerArray<TMsvEntry>&: List of child entries.
+ *
+ * Fetch child entries from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
+	{
+	//Bind the msv id of the entry whose children have to be retrieved
+	BindIntL(iStatement[EGetChildEntries], iParentIdIndex[EGetChildEntries], aParentId);
+
+	while(KSqlAtRow == iStatement[EGetChildEntries].Next())
+		{
+		TMsvId aVisibleParentEntryId;
+		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
+		cacheEntry->Entry().iParentId = aParentId;
+		LoadEntryFromStatementL(iStatement[EGetChildEntries], EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
+		//Add the child entry to the array given
+		aChildArray.AppendL(cacheEntry);
+		}
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iStatement[EGetChildEntries].Reset());
+	}
+
+
+
+
+/**
+ * GetChildrenIdL()
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @return RPointerArray<TMsvEntry>&: List of child entries.
+ *
+ * Fetch child entries from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
+	{
+	//Bind the msv id of the entry whose children have to be retrieved
+	BindIntL(iStatement[EGetChildIds], iParentIdIndex[EGetChildIds], aParentId);
+
+	while(KSqlAtRow == iStatement[EGetChildIds].Next())
+		{
+		TMsvId id = ColumnInt(iStatement[EGetChildIds], iIdIndex[EGetChildIds]);
+		//Add the child Id to the array given
+		aChildArray.AppendL(id);
+		}
+
+	//Reset the RSqlStatement	
+	User::LeaveIfError(iStatement[EGetChildIds].Reset());
+	}
+
+
+
+
+/**
+ * GetChildrenL()
+ * @param TDesc: Partial query string. (Where clause condition).
+ *               The query string should start with 'AND' and should 
+ *               end with a semicolon. Examples are:
+ *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
+ * @param TMsvId: Parent Id of the child entries to be fetched.
+ * @return RPointerArray<TMsvEntry>&: List of child entries.
+ *
+ * Fetch child entries from the database for a given parent Id.
+ * This does not check if the parent entry already exist. The 
+ * entries will be added in ascending order of their TMsvId.
+ */
+void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
+	{
+	_LIT8(KQueryString, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
+			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
+			"reserved, visibleParent, description, details FROM IndexEntry "
+			"WHERE parentId = :parentId ");
+
+	RSqlStatement condGetChildrenStmnt;
+	CleanupClosePushL(condGetChildrenStmnt);
+	TInt len = KQueryString().Length() + aQueryStr.Length();
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(len);	
+	queryBuf.Append(KQueryString);
+	queryBuf.Append(aQueryStr);
+		
+	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
+	TInt index = 0;
+
+	//Bind the msv id of the entry whose children have to be retrieved
+	BindIntL(condGetChildrenStmnt, index, aParentId);
+
+	while(KSqlAtRow == condGetChildrenStmnt.Next())
+		{
+		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
+		cacheEntry->Entry().iParentId = aParentId;
+
+		index = 0;
+		cacheEntry->Entry().iId = ColumnInt(condGetChildrenStmnt, index);
+		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iType.iUid = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iData = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
+		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
+		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
+		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
+		
+		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
+		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
+		
+		//Add the child entry to the array given
+		aChildArray.AppendL(cacheEntry);
+		}
+	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
+	}
+
+
+
+
+/**
+ * EntryExistsL()
+ * @param TMsvId: Entry Id to check.
+ * @return TBool: ETrue if the entry exists, otherwise EFalse.
+ */
+TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
+	{	
+	_LIT8(KEntryExistsQuery, "SELECT id FROM IndexEntry WHERE id = ");
+	_LIT8(KEndDelimeter, ";");
+	
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	TInt len = KEntryExistsQuery().Length() + 10 + KEndDelimeter().Length(); //10 = space for TMsvId
+	queryBuf.CreateL(len);
+	queryBuf.Append(KEntryExistsQuery);
+	queryBuf.AppendNum(aId);
+	queryBuf.Append(KEndDelimeter);
+	TSqlScalarFullSelectQuery query(iDatabase);
+	TMsvId id = NULL;
+	TRAPD(err, id = query.SelectIntL(queryBuf));
+	CleanupStack::PopAndDestroy();		// queryBuf
+	if(err!= KErrNone && err!= KErrNotFound)
+		{
+		User::Leave(err);
+		}
+	if(id)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+	
+	
+	
+	
+/**
+ * GetMaxTMsvIdL()
+ * @param TMsvId&: Out parameter for maximum TMsvId in the database.
+ * @return None.
+ * 
+ * If there are no entries in the database (DB is empty),
+ * the aMaxTMsvId is set to NULL.
+ */
+void CMsvDBAdapter::GetMaxTMsvIdL(TMsvId& aMaxTMsvId)
+	{
+	_LIT8(KQuery, "SELECT MAX(id) FROM IndexEntry;");
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(35);
+	queryBuf.Append(KQuery);
+
+	//Create a select query
+    TSqlScalarFullSelectQuery query(iDatabase);
+
+	//Get the column data
+    aMaxTMsvId = query.SelectIntL(queryBuf);
+    CleanupStack::PopAndDestroy();
+	}
+
+
+
+
+/**
+ * GetInPreparationIdL()
+ * @param aSelection CMsvEntrySelection of the TMsvEntries 
+ * 					 whose KMsvEntryInPreparationFlag is set
+ * @return void
+ */
+void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection)
+	{
+	RSqlStatement statement;	
+	User::LeaveIfError(statement.Prepare(iDatabase, KGetInPreparationIdQuery));
+	
+	TInt paramIdColumn = GetColumnIndexL(statement, KMsgColumnId());
+	TInt paramDataColumn = GetColumnIndexL(statement, KMsgColumnData());
+	
+	TMsvId Id;
+	TInt32 data;
+	while (KSqlAtRow == statement.Next())
+		{
+		data = ColumnInt(statement, paramDataColumn);
+		if( data & TMsvEntry::KMsvEntryInPreparationFlag )
+			{
+			Id = ColumnInt(statement, paramIdColumn);
+			aSelection.AppendL(Id);
+			}
+		}	
+	statement.Close();
+	}
+
+
+
+
+/**
+ * GetVisibleFlagL()
+ *@param TMsvId : the Id of the entry whose flag is to be checked.
+ *@return TBool : ETrue if the entry is visible, EFalse otherwise.
+ *
+ * Returns the status of the visible flag of an entry in the DB.
+ */
+TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId entryId)
+	{
+	_LIT8(KGetVisibleFlagQuery, "SELECT data FROM IndexEntry "
+								"WHERE id = ");
+	_LIT8(KEndDelimeter, ";");
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(60);	
+	queryBuf.Append(KGetVisibleFlagQuery);
+	queryBuf.AppendNum(entryId);
+	queryBuf.Append(KEndDelimeter);
+	TSqlScalarFullSelectQuery query(iDatabase);
+	TInt32 data = 0;
+	TRAPD(err, data = query.SelectIntL(queryBuf));
+	CleanupStack::PopAndDestroy(); //queryBuf
+	if(err!= KErrNone && err!= KErrNotFound)
+		{
+		User::Leave(err);
+		}
+	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
+		{
+		return EFalse;
+		}
+	else
+		{
+		return ETrue;
+		}
+	}
+
+
+
+
+/**
+ * UpdateVisibleFolderL()
+ * @param RBuf8 : the ID's of the entries of whose visible parent is to 
+ *				  be updated.
+ * @return None.
+ *
+ * Updates the visible parent of the entries passed through the RBuf* idList.
+ */
+ void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* entryList, TMsvId newVisibleFolderId)
+ 	{
+ 	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE IndexEntry SET "
+										"visibleParent = ");
+	_LIT8(KUpdateVisibleFolderQuery2,	" WHERE id IN ( ");
+	_LIT8(KComma, ", ");
+	_LIT8(KDelimiter, ");");
+	
+	BeginTransactionL();
+						
+	TInt count = entryList->Count();
+	TInt arrIndex = 0;
+	while(arrIndex < count)
+		{
+		TInt len = KUpdateVisibleFolderQuery1().Length() + KUpdateVisibleFolderQuery2().Length(); 
+		TInt temp;
+		//Update 50 entries or lesser at a time.
+		
+		TInt totalEntries = count - arrIndex;
+		
+		if(totalEntries < 50)
+			{
+			len += totalEntries*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
+			temp = totalEntries;
+			}
+		else
+			{
+			len += 50*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
+			temp = 50;
+			}
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(len);
+		queryBuf.Append(KUpdateVisibleFolderQuery1);
+		queryBuf.AppendNum(newVisibleFolderId);
+		queryBuf.Append(KUpdateVisibleFolderQuery2);
+		TInt index = arrIndex;
+		for(; index < arrIndex + temp; ++index)
+			{
+			queryBuf.AppendNum(entryList->At(index));
+			if(index != arrIndex + temp - 1)
+				{
+				queryBuf.Append(KComma);
+				}
+			}
+		queryBuf.Append(KDelimiter);
+		arrIndex += temp;	
+		TInt err = iDatabase.Exec(queryBuf);
+		CleanupStack::PopAndDestroy();	// queryBuf
+		if(err < 0)
+			{			
+			RollbackTransactionL();
+			User::Leave(err);
+			}
+		else if(!err) //no entries updated
+			{
+			RollbackTransactionL();
+			User::Leave(KErrNotFound);
+			}
+		}
+	CommitTransactionL();
+	}
+
+
+
+
+/**
+ * UpdateOwnerStatusL()
+ *
+ * @param TMsvId : the Id of an entry which has had a child added
+ *				   under it and needs its owner flag updated.
+ * @return None.
+ *
+ * The function updates the owner flag of an entry which has had a
+ * child added under it.
+ */
+void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
+	{
+	_LIT8(KUpdateOwnershipQuery1,	"UPDATE IndexEntry SET "
+										" data = ");
+	_LIT8(KUpdateOwnershipQuery2,	" WHERE id = ");
+	_LIT8(KDelimiter, ";");
+	
+	// Owner flag has already been set. Return to caller.
+	if(aParent.Owner() && aSet)
+		{
+		return;
+		}
+	// Otherwise update the owner flag for the entry in the DB.
+	else
+		{
+		TInt32 data;
+		if(aSet)
+			{
+			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
+			}
+		else
+			{
+			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
+			}
+		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
+		len += 100; //data and TMsvId.
+		RBuf8 queryBuf;
+		CleanupClosePushL(queryBuf);
+		queryBuf.CreateL(len);		
+		queryBuf.Append(KUpdateOwnershipQuery1);
+		queryBuf.AppendNum(data);
+		queryBuf.Append(KUpdateOwnershipQuery2);
+		queryBuf.AppendNum(aId);
+		queryBuf.Append(KDelimiter);
+		TInt err = iDatabase.Exec(queryBuf);
+		if(err < 0)
+			{
+			User::Leave(err);
+			}
+		CleanupStack::PopAndDestroy(); //queryBuf
+		}
+	}
+
+
+
+#endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+
+
+
+/**
+ * InitializeL()
+ *
+ * This functions prepares (compiles) frequetly used SQL queries,
+ * and create indexes on the variable arguments. When the query
+ * needs to be executed, we just have to bind the variables with
+ * the values and execute them. This increases the performance of
+ * query execution.
+ */
+void CMsvDBAdapter::InitializeL()
+	{
+	//Prepare the frequently used SQL statements
+	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
+	User::LeaveIfError(iStatement[EUpdateEntry].Prepare(iDatabase, KUpdateEntryQuery));
+	User::LeaveIfError(iStatement[EUpdateEntryNoParent].Prepare(iDatabase, KUpdateEntryNoParentQuery));
+	User::LeaveIfError(iStatement[EGetEntry].Prepare(iDatabase, KGetEntryQuery));
+	User::LeaveIfError(iStatement[EGetChildEntries].Prepare(iDatabase, KGetChildEntriesQuery));
+	User::LeaveIfError(iStatement[EGetVisibleId].Prepare(iDatabase, KGetVisibleIdQuery));
+	User::LeaveIfError(iStatement[EEntryExists].Prepare(iDatabase, KGetEntryExistsQuery));
+	User::LeaveIfError(iStatement[EGetChildIds].Prepare(iDatabase, KGetChildIdsQuery));
+
+	//Get the indices - This maps the parameter name to its offset
+	//in the SQL statement templates.
+	for(TInt index = ECreateEntry; index < EIndexSentinel; ++index)
+		{
+		switch(index)
+			{
+			case ECreateEntry:			// KCreateEntryQuery
+			case EUpdateEntry:			// KUpdateEntryQuery
+				//For creating and updating entries
+				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
+				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
+				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
+				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
+				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
+				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
+				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
+				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
+				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
+				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
+				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
+				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
+				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
+				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
+				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
+				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
+				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
+				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
+				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
+				break;
+			case EUpdateEntryNoParent:
+				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
+				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
+				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
+				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
+				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
+				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
+				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
+				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
+				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
+				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
+				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
+				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
+				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
+				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
+				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
+				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
+				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
+				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
+				break;
+			case EGetEntry:				// KGetEntryQuery
+				//Read an entry from DB
+				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
+				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
+				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
+				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
+				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
+				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
+				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
+				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
+				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
+				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
+				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
+				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
+				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
+				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
+				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
+				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
+				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
+				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
+				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
+				break;
+			case EGetChildEntries:		// KGetChildEntriesQuery
+				//Read child entries for a given parent Id.
+				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
+				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
+				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
+				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
+				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
+				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
+				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
+				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
+				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
+				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
+				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
+				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
+				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
+				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
+				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
+				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
+				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
+				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
+				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
+				break;
+			case EGetVisibleId:			// KGetVisibleIdQuery
+				//For getting visible Id related information
+				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
+				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());	
+				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
+				break;
+			case EEntryExists:			// KGetEntryExistsQuery
+				//To check if an entry exists in DB.
+				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
+				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
+				break;
+			case EGetChildIds:			// KGetChildIdsQuery
+				//To check if an entry exists in DB.
+				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
+				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
+				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
+#endif
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+
+
+
+/**
+ * BeginTransactionL()
+ * 
+ * Starts a new DB transaction.
+ */
+void CMsvDBAdapter::BeginTransactionL()
+	{
+	if(!isTransactionOpen)
+		{
+		_LIT8(KBeginTransaction, "BEGIN;");
+		User::LeaveIfError(iDatabase.Exec(KBeginTransaction));
+		isTransactionOpen = ETrue;
+		}
+	}
+
+
+
+
+/**
+ * CommitTransactionL()
+ * 
+ * Commits an already opened transaction.
+ */
+void CMsvDBAdapter::CommitTransactionL()
+	{
+	if(isTransactionOpen)
+		{
+		_LIT8(KCommitTransaction,	 "COMMIT;");
+		isTransactionOpen = EFalse;
+		User::LeaveIfError(iDatabase.Exec(KCommitTransaction));		
+		}
+	}
+
+
+/**
+ * RollbackTransactionL()
+ * 
+ * Rollback an already opened transaction.
+ */
+void CMsvDBAdapter::RollbackTransactionL()
+	{
+	if(isTransactionOpen)
+		{
+		_LIT8(KRollbackTransaction,	 "ROLLBACK;");
+		isTransactionOpen = EFalse;
+		User::LeaveIfError(iDatabase.Exec(KRollbackTransaction));		
+		}
+	}
+
+
+
+
+
+/**
+ * LoadEntryFromStatementL()
+ * @param RSqlStatement&: a reference to the RSqlStatement to work against.
+ * @param TInt: Index of the SQL statement.
+ * @param TMsvId&: Out parameter for value of VisibleParent column.
+ * @param CMsvCacheEntry&: The newly fetched entry to be filled.
+ * @return None.
+ *
+ * Creates a CMsvCacheEntry from the executed RSqlStatement.
+ */
+void CMsvDBAdapter::LoadEntryFromStatementL(RSqlStatement& aStmt, TInt aIndex, TMsvId& aVisibleParentEntryId, CMsvCacheEntry& aEntry)
+	{
+	if(EGetEntry != aIndex)
+		{
+		aEntry.Entry().iId = ColumnInt(aStmt, iIdIndex[aIndex]);
+		}
+	if(EGetChildEntries != aIndex)
+		{
+		aEntry.Entry().iParentId = ColumnInt(aStmt, iParentIdIndex[aIndex]);
+		}
+	
+	aEntry.Entry().iData = ColumnInt(aStmt, iDataIndex[aIndex]);
+	aEntry.Entry().iPcSyncCount = ColumnInt(aStmt, iPcSyncCountIndex[aIndex]);
+	aEntry.Entry().iReserved = ColumnInt(aStmt, iReservedIndex[aIndex]);
+	aEntry.Entry().iRelatedId = ColumnInt(aStmt, iRelatedIdIndex[aIndex]);
+	aEntry.Entry().iType.iUid = ColumnInt(aStmt, iTypeIndex[aIndex]);
+	aEntry.Entry().iDate = ColumnInt64(aStmt, iDateIndex[aIndex]);
+	aEntry.Entry().iSize = ColumnInt(aStmt, iSizeIndex[aIndex]);
+	aEntry.Entry().iError = ColumnInt(aStmt, iErrorIndex[aIndex]);
+	aEntry.Entry().iBioType = ColumnInt(aStmt, iBiotypeIndex[aIndex]);
+	aEntry.Entry().iMtmData1 = ColumnInt(aStmt, iMtmData1Index[aIndex]);
+	aEntry.Entry().iMtmData2 = ColumnInt(aStmt, iMtmData2Index[aIndex]);
+	aEntry.Entry().iMtmData3 = ColumnInt(aStmt, iMtmData3Index[aIndex]);
+	aEntry.Entry().iServiceId = ColumnInt(aStmt, iServiceIdIndex[aIndex]);
+	aEntry.Entry().iMtm.iUid = ColumnInt(aStmt, iMtmIdIndex[aIndex]);
+	aEntry.iDescriptionBuffer = ColumnTextL(aStmt, iDescriptionIndex[aIndex]);
+	aEntry.Entry().iDescription.Set(*aEntry.iDescriptionBuffer);
+	aEntry.iDetailsBuffer = ColumnTextL(aStmt, iDetailsIndex[aIndex]);
+	aEntry.Entry().iDetails.Set(*aEntry.iDetailsBuffer);
+	
+	//Get the visible parent id
+	aVisibleParentEntryId = ColumnInt(aStmt, iVisibleParent[aIndex]);
+	}
+
+
+
+
+/**
+ * GetNextSiblingL()
+ *
+ * @param TMsvId: TMsvId of the entry whose sibling id is to be found.
+ * @param TMsvId: TMsvId of the parent entry of aId.
+ * @param TMsvId&: TMsvId of the sibling of aId, this is an o/p parameter.
+ * @return TBool
+ *
+ * Gets the id of the sibling of aId.
+ */
+TBool CMsvDBAdapter::GetNextSiblingL(TMsvId aId,TMsvId aParentId,TMsvId& aNextSiblingId)
+	{
+	TBool foundSibling=EFalse;
+	//get all the children for this parent
+	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
+	CleanupStack::PushL(children);
+	GetChildrenIdL(aParentId,*children);
+	TInt childCount=children->Count();
+	
+	for(TInt i=0;i<childCount;++i)
+		{
+		if(children->At(i)==aId && i<childCount-1)
+			{
+			aNextSiblingId=children->At(i+1);
+			foundSibling=ETrue;
+			break;
+			}
+		}
+	CleanupStack::PopAndDestroy(children);
+	return foundSibling;
+	}
+
+
+
+/**
+ * GetFirstChildIdL()
+ *
+ * @param TMsvId: TMsvId of the parent entry of aId.
+ * @param TMsvId: TMsvId of the child of aParentId, this is an o/p parameter.
+ * @return TBool.
+ *
+ * Gets the id of first child of aParentId.
+ */
+TBool CMsvDBAdapter::GetFirstChildIdL(TMsvId aParentId,TMsvId& aFirstChild)
+	{
+	TBool foundChild=EFalse;
+	//get all the children for this parent
+	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
+	CleanupStack::PushL(children);
+	GetChildrenIdL(aParentId,*children);
+	TInt childCount=children->Count();
+	
+	if(childCount>0)
+		{
+		aFirstChild=children->At(0);
+		foundChild=ETrue;
+		}
+	CleanupStack::PopAndDestroy(children);
+	return foundChild;
+	}
+
+
+/**
+ * ConstructSortTableL()
+ * @param none.
+ * #return none.
+ * 
+ * This functions is called to create a new table,
+ * which stores the information for the search/sort
+ * operations performed.
+ */ 
+void CMsvDBAdapter::ConstructSortTableL()
+	{
+		
+	//Create Search Sort Cache table. This stores the results of
+	// search sort result	
+	TInt err = iDatabase.Exec(KCreateSearchSortEntryTableQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	if(err == 0)
+		{
+		ClearDBContentsL();
+		}
+#endif
+	
+	//Create Unique index's on indexEnty table.
+	//Unique Index is created on all columns to defer duplicates.
+	err = iDatabase.Exec(KCreateSearchSortQuery);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	}
+
+
+
+
+/**
+ * InitializeSortTableL()
+ * @param none.
+ * #return none.
+ * 
+ * This functions prepares (compiles) frequetly used SQL queries,
+ * and create indexes on the variable arguments. When the query
+ * needs to be executed, we just have to bind the variables with
+ * the values and execute them. This increases the performance of
+ * query execution.
+ */
+void CMsvDBAdapter::InitializeSortTableL()
+	{						 
+	//Prepare the frequently used SQL statements
+	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Prepare(iDatabase, KCreateQueryEntry));
+	User::LeaveIfError(iQueryStatement[EQueryGetEntryAsc].Prepare(iDatabase, KGetEntryAsc));
+	User::LeaveIfError(iQueryStatement[EQueryGetEntryDesc].Prepare(iDatabase, KGetEntryDesc));
+	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumAsc].Prepare(iDatabase, KGetEntryNumAsc));
+	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumDesc].Prepare(iDatabase, KGetEntryNumDesc));
+	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsAsc].Prepare(iDatabase, KGetLastNIdsAsc));
+	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsDesc].Prepare(iDatabase, KGetLastNIdsDesc));
+	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumAsc].Prepare(iDatabase, KGetLastNIdsNumAsc));
+	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumDesc].Prepare(iDatabase, KGetLastNIdsNumDesc));
+	User::LeaveIfError(iQueryStatement[EGetFolderIds].Prepare(iDatabase, KGetFolderIds));
+	User::LeaveIfError(iQueryStatement[EQueryCount].Prepare(iDatabase, KGetQueryCount));
+	User::LeaveIfError(iQueryStatement[EQueryIteratorNumAsc].Prepare(iDatabase, KGetIterResultCastAsc));
+	User::LeaveIfError(iQueryStatement[EQueryIteratorNumDesc].Prepare(iDatabase, KGetIterResultCastDesc));
+	User::LeaveIfError(iQueryStatement[EQueryIteratorAsc].Prepare(iDatabase, KGetIterResultAsc));
+	User::LeaveIfError(iQueryStatement[EQueryIteratorDesc].Prepare(iDatabase, KGetIterResultDesc));
+
+	//Get the indices - This maps the parameter name to its offset
+	//in the SQL statement templates.
+	for(TInt index = EQueryCreateEntry; index < EQuerySentinel; ++index)
+		{
+		switch(index)
+			{							 
+			case EQueryCreateEntry:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryTMsvId());
+				iSortfieldQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQuerySortfield());
+				break;
+				}
+
+			case EQueryGetEntryAsc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+
+			case EQueryGetEntryDesc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+				
+			case EQueryGetEntryNumAsc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+
+			case EQueryGetEntryNumDesc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+				
+			case EQueryGetLastNIdsAsc:
+				{
+				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+				
+			case EQueryGetLastNIdsDesc:
+				{
+				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
+				break;
+				}
+		
+			case EQueryGetLastNIdsNumAsc:
+				{
+				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
+				break;
+				}
+			
+			case EQueryGetLastNIdsNumDesc:
+				{
+				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
+				break;
+				}
+				
+			case EGetFolderIds:
+				{
+				iParentIdfield = GetParamIndexL(iQueryStatement[index], KMsgParamParentId());
+				iTMsvidfield = GetParamIndexL(iQueryStatement[index], KMsgParamType());
+				break;
+				}
+					
+			case EQueryCount:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				break;
+				}
+			
+			case EQueryIteratorNumAsc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
+				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
+				break;
+				}
+			
+			case EQueryIteratorNumDesc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
+				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
+				break;
+				}
+			
+			case EQueryIteratorAsc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
+				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
+				break;
+				}
+			
+			case EQueryIteratorDesc:
+				{
+				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
+				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
+				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
+				break;
+				}
+
+			default:
+				break;
+			}
+		}
+	}
+
+
+
+	
+/**
+ * CreateQueryEntryL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @param TMsvIdWithSortField&: Fields to be added under the query id specified
+ * @return none.
+ *
+ * This Function adds the Entries into the DB under the Queryid specified
+ */
+void CMsvDBAdapter::CreateQueryEntryL(const TInt& aQueryId,const TMsvIdWithSortField& aEntry)
+	{
+	//Bind the entry data
+	BindIntL(iQueryStatement[EQueryCreateEntry], iQIdQueryIndex[EQueryCreateEntry], aQueryId);
+	
+	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], UnmaskTMsvId(aEntry.iMessageId));
+	#else
+		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], aEntry.iMessageId);
+	#endif		
+	
+	
+	BindTextL(iQueryStatement[EQueryCreateEntry], iSortfieldQueryIndex[EQueryCreateEntry], aEntry.iContentMessagePart);
+		
+	TInt err = iQueryStatement[EQueryCreateEntry].Exec();
+	if(err < 0)
+		{
+		iQueryStatement[EQueryCreateEntry].Reset();
+		User::Leave(err);
+		}
+	
+	//Reset the RSqlStatement
+	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Reset());
+	}
+	
+
+
+
+/**
+ * GetSortedEntriesL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
+ * #param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
+ * @return none.
+ *
+ * This Function retrieves all the ids under the specified Query Id
+ */
+void CMsvDBAdapter::GetSearchSortEntriesL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, const TBool aOrder/*Default = EFalse*/,const TBool aSortAsInt/*Default = EFalse*/)
+	{
+	TInt sortOrder;
+	TMsvId entryId;
+	
+	if(aSortAsInt)
+		{
+		if(aOrder)
+			{
+			sortOrder = EQueryGetEntryNumAsc;
+			}
+		else
+			{
+			sortOrder = EQueryGetEntryNumDesc;
+			}
+		}
+	else
+		{
+		if(aOrder)
+			{
+			sortOrder = EQueryGetEntryAsc;
+			}
+		else
+			{
+			sortOrder = EQueryGetEntryDesc;
+			}
+		}
+	
+	//Bind the msv id of the entry to be retrieved
+	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
+
+	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
+		{
+		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
+		
+		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			entryId = MaskTMsvId(KCurrentDriveId,entryId);
+		#endif
+		
+		aEntrySelection.AppendL(entryId);
+		}
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
+	}
+
+
+
+
+/**
+ * GetLastNTMsvIdsfromTableL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
+ * @param TInt aLastCount: The Number of entries from the last rowid to be fetched from
+ * @param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
+ * @return none.
+ *
+ * This Function retrieves the last N ids under the specified Query Id
+ */
+void CMsvDBAdapter::GetLastNTMsvIdsfromTableL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, TInt aLastCount, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/)
+	{
+	TInt sortOrder;
+	TMsvId entryId;
+
+	if(aSortAsInt)
+		{
+		if(aOrder)
+			{
+			sortOrder = EQueryGetLastNIdsAsc;
+			}
+		else
+			{
+			sortOrder = EQueryGetLastNIdsDesc;
+			}
+		}
+	else
+		{
+		if(aOrder)
+			{
+			sortOrder = EQueryGetLastNIdsNumAsc;
+			}
+		else
+			{
+			sortOrder = EQueryGetLastNIdsNumDesc;
+			}
+		}
+	
+	//Bind the count value
+	BindIntL(iQueryStatement[sortOrder], iRowIdIndex[sortOrder], aLastCount);
+	
+	//Bind the msv id of the entry to be retrieved
+	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
+
+	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
+		{
+		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
+		
+		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			entryId = MaskTMsvId(KCurrentDriveId, entryId);
+		#endif
+		
+		aEntrySelection.AppendL(entryId);
+		}
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
+	}
+
+
+
+
+/**
+ * DeleteTMsvIdFromAllQueriesL()
+ * @param TMsvId&: The id to be deleted
+ * @return none.
+ *
+ * This Function delete a id under all Queryid's
+ */
+void CMsvDBAdapter::DeleteTMsvIdFromAllQueriesL(const TMsvId& aId)
+	{	
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(KDeleteId().Length() + 20);
+	queryBuf.Append(KDeleteId);
+	queryBuf.AppendNum(aId);
+	queryBuf.Append(KSemiColon);
+	
+	TInt err = iDatabase.Exec(queryBuf);
+	CleanupStack::PopAndDestroy();		// queryBuf
+	if(err < 0)
+		{		
+		User::Leave(err);
+		}
+	}
+
+
+
+
+/**
+ * DeleteQueryFromTableL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @return none.
+ *
+ * This Function deletes a particular Query from DB
+ */
+void CMsvDBAdapter::DeleteQueryFromTableL(const TInt& aQueryId)
+	{
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(KDeleteQueryId().Length() + 20);
+	queryBuf.Append(KDeleteQueryId);
+	queryBuf.AppendNum(aQueryId);
+	queryBuf.Append(KSemiColon);
+	
+	TInt err = iDatabase.Exec(queryBuf);
+	CleanupStack::PopAndDestroy();		// queryBuf
+	if(err < 0)
+		{		
+		User::Leave(err);
+		}
+	}
+
+
+
+
+/**
+ * DeleteTMsvIdFromQueryL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @param TMsvId&: The TMsvId of the entry to be deleted 
+ * @return none.
+ *
+ * This Function deletes a particular id under the specified QueryId
+ */
+void CMsvDBAdapter::DeleteTMsvIdFromQueryL(const TInt& aQueryId,const TMsvId& aId)
+	{
+	RBuf8 queryBuf;
+	CleanupClosePushL(queryBuf);
+	queryBuf.CreateL(KDeleteQueryId().Length()+KAndId().Length() + 20);
+	queryBuf.Append(KDeleteQueryId);
+	queryBuf.AppendNum(aQueryId);
+	queryBuf.Append(KAndId);
+	queryBuf.AppendNum(aId);
+	queryBuf.Append(KSemiColon);
+	
+	TInt err = iDatabase.Exec(queryBuf);
+	CleanupStack::PopAndDestroy();		// queryBuf
+	if(err < 0)
+		{		
+		User::Leave(err);
+		}
+	}
+
+
+
+
+/**
+ * AddEntriesfromIndexTableL()
+ * @param TDesC8&: The Query to fill the SearchSortTable with the IndexEntry
+ * @return number of entries successfully added.
+ *
+ * This Function fills the SearchSortTable with the query specified on the IndexEntryTable
+ */
+TInt CMsvDBAdapter::AddEntriesfromIndexTableL(const TDesC8& aQuery)
+	{
+	TInt err = iDatabase.Exec(aQuery);
+	
+	TPtrC errMsg = iDatabase.LastErrorMessage();
+	
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+
+	return err;
+	}
+
+
+
+
+/**
+ * ReturnIdCountInDBL()
+ * @param TInt&: The Id of the Search/Sort Query
+ * @return TInt: The number of entries stored under the QueryId specified
+ *
+ * This Function returns the number of id's stored under the specified QueryId
+ */
+TInt CMsvDBAdapter::ReturnIdCountInDBL(const TInt& aQueryId)
+	{
+	TInt count=0;
+	//Bind the msv id of the entry to be retrieved
+	BindIntL(iQueryStatement[EQueryCount], iQIdQueryIndex[EQueryCount], aQueryId);
+
+	while(KSqlAtRow == iQueryStatement[EQueryCount].Next())
+		{
+		count = ColumnInt(iQueryStatement[EQueryCount], iIdQueryIndex[EQueryCount]);
+		}
+
+	//Reset the RSqlStatement
+	User::LeaveIfError(iQueryStatement[EQueryCount].Reset());
+	return count;
+	}
+
+
+
+
+/**
+ * SearchTMsvIdL()
+ * @param aQuery        An object representing the the search sort query.
+ * @param aIdSelection  RArray holding the resultant TMsvId list. 
+ * 
+ * This function should be used to retrieve TMsvId list of result set.					 
+ * Queries the table holding TMsvEntry and retrieves id list of matched results.
+ */
+void CMsvDBAdapter::SearchTMsvIdL(const TDesC8& aQuery, RArray<TMsvId>& aIdSelection)
+	{
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
+	
+	TInt idColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		
+		TMsvId id = ColumnInt(queryStmt, idColumnIndex);
+		
+		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			id = MaskTMsvId(KCurrentDriveId, id);
+		#endif
+		
+		aIdSelection.AppendL(id);
+		}
+
+	CleanupStack::PopAndDestroy();
+	}
+
+
+
+
+/**
+ * GetFolderIdsL()
+ * @param aParentId      Parent Id of the folder.
+ * @param aFolderIdList  RArray holding the resultant TMsvId list. 
+ * 
+ * This function returns the id's of all the KUidMsvMessageEntry type under the parent.
+ */
+void CMsvDBAdapter::GetFolderIdsL(const TMsvId aParentId, RArray<TMsvId>& aFolderIdList)
+	{
+	TMsvId entryId;
+	TUid folderType = KUidMsvFolderEntry;
+	
+	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		{
+		_LIT8(KGetFolderIds, "SELECT id FROM DB");
+		_LIT8(KGetFolderQuery,".IndexEntry WHERE parentId = ");
+	
+		_LIT8(KTypeLike," AND type = ");
+
+		RBuf8 folderIdQuery;
+		CleanupClosePushL(folderIdQuery);
+		folderIdQuery.CreateL(500);		
+		folderIdQuery.Append(KGetFolderIds);
+		folderIdQuery.AppendNum(KCurrentDriveId);
+		folderIdQuery.Append(KGetFolderQuery);
+		folderIdQuery.AppendNum(aParentId);
+		folderIdQuery.Append(KTypeLike);
+		folderIdQuery.AppendNum(folderType.iUid);
+		folderIdQuery.Append(KSemiColon);
+	
+		RSqlStatement folderquerystatement;
+	
+		User::LeaveIfError(folderquerystatement.Prepare(iDatabase, folderIdQuery));
+	
+		while(KSqlAtRow == folderquerystatement.Next())
+			{
+			entryId = ColumnInt(folderquerystatement, 0);
+			aFolderIdList.AppendL(entryId);
+			}
+		folderquerystatement.Close();
+		CleanupStack::PopAndDestroy();  //folderIdQuery
+		}
+	#else
+		{
+		//Bind the msv id of the entry to be retrieved
+		BindIntL(iQueryStatement[EGetFolderIds], iParentIdfield, aParentId);
+		BindIntL(iQueryStatement[EGetFolderIds], iTMsvidfield, folderType.iUid);
+		
+		while(KSqlAtRow == iQueryStatement[EGetFolderIds].Next())
+			{
+			entryId = ColumnInt(iQueryStatement[EGetFolderIds], iParentIdfield);
+			aFolderIdList.AppendL(entryId);
+			}
+		//Reset the RSqlStatement
+		User::LeaveIfError(iQueryStatement[EGetFolderIds].Reset());
+		}
+	#endif
+	}
+
+
+
+
+/**
+ * ClearDBContentsL()
+ * @param none.
+ * @param none.
+ * 
+ * This function clears the DB contents.
+ */
+void CMsvDBAdapter::ClearDBContentsL()
+	{
+#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	RSqlDatabase temp;
+	CleanupClosePushL(temp);
+	//Get the system drive.
+	TInt systemDrive = (TInt)RFs::GetSystemDrive();
+	
+	RBuf dbFile;
+	CleanupClosePushL(dbFile);
+	dbFile.CreateL(50);	
+	dbFile.Append(TDriveUnit(systemDrive).Name());
+	dbFile.Append(KMainDummyDBName);
+	
+	TRAPD(err, temp.OpenL(dbFile));
+	if(err == KErrNone)
+		{
+		err = temp.Exec(KClearTableContents);
+		if(err < 0)
+			{
+			User::Leave(err);
+			}
+		}
+	temp.Close();
+	CleanupStack::PopAndDestroy(2); //temp, dbFile
+#else
+	TInt err = iDatabase.Exec(KDeleteTable);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+#endif	
+	
+	}
+
+
+
+
+/**
+ * ReturnIdsInIteratorL()
+ * @param aQueryId      Query ID of the query to be executed.
+ * @param prevCount     The previous value returned to the caller. 
+ * @param aId           If successfull, than this contains the result.
+ 
+ * This function returns the TMsvId's for each unique Query ID.
+   Upon called for the first time, it binds the query id to the statement and returns 
+   next result in each subsequent execution. If the statement fails for some reason, than it returns the 
+   error code.	
+ */
+void CMsvDBAdapter::ReturnIdsInIteratorL(const TInt& aQueryId, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/,const TInt aLimit/*Default = 1*/)
+	{
+	if(aSortAsInt)
+		{
+		if(aOrder)
+			{
+			iIterQuery = EQueryIteratorNumAsc;
+			}
+		else
+			{
+			iIterQuery = EQueryIteratorNumDesc;
+			}
+		}
+	else
+		{
+		if(aOrder)
+			{
+			iIterQuery = EQueryIteratorAsc;
+			}
+		else
+			{
+			iIterQuery = EQueryIteratorDesc;
+			}
+		}
+		
+	iOffsetValue = 0;
+	iQueryId = aQueryId;
+	iLimit = aLimit;
+	
+	iIdColumnIndex = GetColumnIndexL(iQueryStatement[iIterQuery], KMsgColumnId());	
+	}
+
+/**
+ * GetNextL()
+ * @param aId           If successfull, than this contains the result.
+ 
+ * This function returns the next TMsvId's from the Iterator	
+ */	
+TInt CMsvDBAdapter::GetNextL(TMsvId& aId)
+	{
+	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
+	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
+	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
+	
+	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
+		{
+		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
+		
+		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aId = MaskTMsvId(KCurrentDriveId, aId);
+		#endif
+			
+		++iOffsetValue;
+		}
+	
+	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
+	return iOffsetValue;
+	}
+	
+
+/**
+ * GetPrevL()
+ * @param aId           If successfull, than this contains the result.
+ 
+ * This function returns the previous TMsvId's from the Iterator	
+ */
+TInt CMsvDBAdapter::GetPrevL(TMsvId& aId)
+	{
+	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
+	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
+	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
+	
+	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
+		{
+		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
+		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aId = MaskTMsvId(KCurrentDriveId, aId);
+		#endif
+		
+		--iOffsetValue;
+		}
+	
+	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
+	return iOffsetValue;
+	}
+
+
+
+
+
+#if (!defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+/**
+ * ValidateDatabaseL()
+ * 
+ * @param TFileName& The database filename to be checked.
+ * @return None.
+ *
+ * Checks the database version to see if it is supported.
+ * Supported version is KCurrentDatabaseVersion (1) only.
+ */
+void CMsvDBAdapter::ValidateDatabaseL(const TFileName& aDbFile)
+	{
+	_LIT8(KSelectVersionQuery, "SELECT version FROM VersionTable;");
+	
+	//Use a temporary local database connection to open the file for now.
+	RSqlDatabase temp;
+	CleanupClosePushL(temp);
+	temp.OpenL(aDbFile);	
+	TSqlScalarFullSelectQuery query(temp);
+
+	TInt version = 0;
+	version = query.SelectIntL(KSelectVersionQuery);
+	if(KCurrentDatabaseVersion != version)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	CleanupStack::PopAndDestroy();  // temp
+	}
+#endif
+
+
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+/** 
+* GetMtmIdsL()
+*
+* @param aMtmIdTable: aMtmIdTable will be updated with MtmIds
+* @param aQuery: QueryString which is prepared depending on SearchSort Query
+* return NONE
+*  
+*  Function to get MtmId/s for given parent id.
+*/ 
+void CMsvDBAdapter::GetMtmIdsL(const TDesC8& aQuery, RArray<TUid>& aMtmIdArray)
+	{
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
+	
+	TInt mtmIdColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnMtmId());
+	
+	TUid tempMtmId ;
+	TInt32 mtmId = KErrNotFound;
+	
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		mtmId = ColumnInt(queryStmt, mtmIdColumnIndex);
+		
+		tempMtmId.iUid = mtmId;
+		aMtmIdArray.AppendL(tempMtmId);
+		}
+	
+	CleanupStack::PopAndDestroy();
+	}
+
+
+
+/***************************** Converter************************/
+
+/**
+OpenL()
+Opens a database and returns a handle to it.
+
+@param aDbFileName: DB name.
+@retun :CMsvDBAdapter object.
+*/	
+CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
+	{
+	//Create an messaging DB adaptor object 
+	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
+	CleanupStack::PushL(self);
+	
+	// Open the database.
+	self->ConstructOpenDBL(aDbFileName);
+	
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+/**
+ConstructOpenDBL()
+
+@param aDbFileName: DB name.
+@retun None
+*/
+void CMsvDBAdapter::ConstructOpenDBL(const TFileName& aDbFileName)
+	{
+	User::LeaveIfError(iDatabase.Open(aDbFileName));
+	iDatabasePresent = new(ELeave)RArray<TBool>(KMaxNumberOfDrives);
+	for(TInt index = 0; index < KMaxNumberOfDrives; ++index)
+		{
+		iDatabasePresent->Append(EFalse);
+		}
+	}
+
+	
+/**
+ * InitializeL()
+ *
+ * This functions prepares (compiles) frequetly used SQL queries,
+ * and create indexes on the variable arguments. When the query
+ * needs to be executed, we just have to bind the variables with
+ * the values and execute them. This increases the performance of
+ * query execution.
+ */
+void CMsvDBAdapter::InitializeLConverterStatementL()
+	{
+	//Prepare the frequently used SQL statements
+	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
+	
+	//For creating and updating entries
+	iParentIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamParentId());
+	iVisibleParent[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamVisibleParent());
+	iIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamId());				
+	iServiceIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamServiceId());
+	iMtmIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmId());
+	iTypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamType());
+	iDateIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDate());
+	iDataIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamData());
+	iSizeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamSize());
+	iErrorIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamError());
+	iMtmData1Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData1());
+	iMtmData2Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData2());
+	iMtmData3Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData3());
+	iRelatedIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamRelatedId());
+	iBiotypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamBiotype());
+	iPcSyncCountIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamPcSyncCount());
+	iReservedIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamReserved());
+	iDescriptionIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDescriptionTxt());
+	iDetailsIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDetailsTxt());
+	}
+
+
+/**
+CreateIndexEntryL()
+Inserts an entry in IndexEntry table.  
+
+@param aNewEntry: TMsvEntry.
+@param aImmediateVisibleFolder: Visible Parent.
+@retun None
+*/
+void CMsvDBAdapter::CreateIndexEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
+	{
+	//Bind the entry data
+	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
+	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
+	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
+	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
+	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
+	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
+	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
+	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
+	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
+	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
+	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
+	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
+	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
+	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
+	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
+	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
+	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
+	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
+	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
+	//Execute the prepared SQL statement.
+	
+	TInt err = iStatement[ECreateEntry].Exec();
+	if(err < 0)
+		{
+		iStatement[ECreateEntry].Reset();
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		iStatement[ECreateEntry].Reset();
+		User::Leave(KErrGeneral);
+		}
+	
+	//Reset the RSqlStatement
+	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
+	}
+
+
+/**
+ChangeVersionL()
+Changes message store version of messaging database.
+
+@param aVersion: version
+@retun None
+*/	
+void CMsvDBAdapter::ChangeVersionL(TInt aVersion)
+	{
+	_LIT(KUpdateVersionQuery, "UPDATE VersionTable SET version = "); 
+		
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KUpdateVersionQuery);
+	buf.AppendNum(aVersion);
+	buf.Append(KDelimiter);
+	
+	TInt err = iDatabase.Exec(buf);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	CleanupStack::PopAndDestroy(); //buf
+	}
+
+	
+/**************************** Conversion Status Table API's **************************/
+/**
+CreateConversionStatusTableL()
+Creates conversion status table.
+
+@param None: 
+@retun None
+*/
+void CMsvDBAdapter::CreateConversionStatusTableL()
+	{
+	TInt err = iDatabase.Exec(KCreateConversionStatusTableQuery);
+	if(err < 0)
+		{
+		User::Leave(KErrGeneral);
+		}
+	}
+
+/**
+RemoveConversionStatusTableL()
+Removes conversion status table.
+
+@param None: 
+@retun None
+*/	
+void CMsvDBAdapter::RemoveConversionStatusTableL()
+	{
+	TInt err = iDatabase.Exec(KRemoveConversionStatusTable);
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	}
+
+/**
+GetConversionStatusL()
+Fetches conversion resume state from the conversion status table.
+
+@param aConversionResumeStatus: Conversion sresume status entry.
+@retun None
+*/	
+void CMsvDBAdapter::GetConversionStatusL(TConversionResumeStatus& aConversionResumeStatus)
+	{
+	// We shld not get more than one mtm results for this query
+	_LIT16(KGetConversionStatusQuery, "SELECT * FROM ConversionStatus WHERE remainingCount != 0;"); 
+	
+	RSqlStatement statement;
+	CleanupClosePushL(statement);
+	TInt index =0;
+	
+	User::LeaveIfError(statement.Prepare(iDatabase, KGetConversionStatusQuery));
+		
+	while(KSqlAtRow ==  statement.Next())
+		{
+		aConversionResumeStatus.lastId = ColumnInt(statement, index);
+		aConversionResumeStatus.serviceId = ColumnInt(statement, ++index);
+		aConversionResumeStatus.sourceVersion = ColumnInt(statement, ++index);
+		aConversionResumeStatus.targetVersion = ColumnInt(statement, ++index);
+		aConversionResumeStatus.mtmId.iUid = ColumnInt(statement, ++index);
+		aConversionResumeStatus.remainingCount = ColumnInt(statement, ++index);
+		index =0;
+		}
+	CleanupStack::PopAndDestroy(); //statement
+	}
+
+/**
+AddConversionStatusEntryL()
+Inserts a conversion status entry in the conversion status table.
+
+@param aConversionResumeStatus: Conversion sresume status entry.
+@retun None
+*/	
+void CMsvDBAdapter::AddConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)
+	{
+	_LIT8(KAddConversionStatusEntryQuery, "INSERT INTO ConversionStatus VALUES ("
+							 ":lastId, :serviceId, :sourceVersion, :targetVersion, :mtmId, :remainingCount);"
+		 ); //
+			 
+	RSqlStatement statement;
+	CleanupClosePushL(statement);
+	TInt index =0;
+	
+	User::LeaveIfError(statement.Prepare(iDatabase,KAddConversionStatusEntryQuery));
+	BindIntL(statement, index++, aConversionResumeStatus.lastId);
+	BindIntL(statement, index++, aConversionResumeStatus.serviceId);
+	BindIntL(statement, index++, aConversionResumeStatus.sourceVersion);
+	BindIntL(statement, index++, aConversionResumeStatus.targetVersion);
+	BindIntL(statement, index++, aConversionResumeStatus.mtmId.iUid);
+	BindIntL(statement, index++, aConversionResumeStatus.remainingCount);
+	
+	TInt err = statement.Exec();
+	
+	CleanupStack::PopAndDestroy(); //statement
+
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err )
+		{
+		User::Leave(KErrGeneral);
+		}
+	}
+
+/**
+UpdateConversionStatusEntryL()
+Updates a conversion status entry in the conversion status table.
+
+@param aConversionResumeStatus:Conversion sresume status entry.
+@retun None
+*/	
+void CMsvDBAdapter::UpdateConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)	
+	{
+	_LIT(KUpdateConversionStatusQuery1,	"UPDATE ConversionStatus SET remainingCount = "); //
+	_LIT(KUpdateConversionStatusQuery2,	" WHERE mtmId = "); //
+	_LIT(KUpdateConversionStatusQuery3,	" AND serviceId = "); //
+	 
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KUpdateConversionStatusQuery1);
+	buf.AppendNum(aConversionResumeStatus.remainingCount);
+	buf.Append(KUpdateConversionStatusQuery2);
+	buf.AppendNum(aConversionResumeStatus.mtmId.iUid);
+	buf.Append(KUpdateConversionStatusQuery3);
+	buf.AppendNum(aConversionResumeStatus.serviceId);
+	buf.Append(KDelimiter); 
+	 
+	TInt err = iDatabase.Exec(buf);
+	CleanupStack::PopAndDestroy(); //buf
+	
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err )
+		{
+		User::Leave(KErrGeneral);
+		}
+	}
+
+/**
+RemoveConversionStatusEntriesL()
+Removes all conversion status entries in the conversion status table.
+
+@param None: 
+@retun None
+*/		
+void CMsvDBAdapter::RemoveConversionStatusEntriesL()	
+	{
+ 	_LIT(KRemoveConversionStatusEntry,	"DELETE FROM ConversionStatus;");
+	
+	RSqlStatement statement;
+	CleanupClosePushL(statement);
+	User::LeaveIfError(statement.Prepare(iDatabase, KRemoveConversionStatusEntry));
+	TInt err = statement.Exec();
+	
+	CleanupStack::PopAndDestroy(); // statement
+	
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(err != KErrNone)
+		{
+		User::Leave(KErrGeneral);
+		}
+	}
+
+/**
+GetRemainingServiceIdsL()
+Fetches all service ids for which the conversion is not complete from the conversion status table.
+
+@param aIdArray:Array of TMsvId.
+@retun None
+*/	
+void CMsvDBAdapter::GetRemainingServiceIdsL(RArray<TMsvId>& aIdArray)
+	{
+	_LIT(KGetToResumeServiceIds, "SELECT serviceId FROM ConversionStatus WHERE remainingCount != 0;"); 	
+	
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, KGetToResumeServiceIds));
+	
+	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
+	
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
+		aIdArray.AppendL(serviceId);
+		}
+	CleanupStack::PopAndDestroy(); // stmt
+	}
+
+/**
+GetAllMessageIdsL()
+Gets all message ids for a service id. If the conversion is resumed than retrives the message ids
+after the last id that was converted. 
+
+@param aServiceId: service id.
+@param aIdArray: Array of TMsvId.
+@param lastId: last id that was converted and commited in the database.
+@retun None
+*/	
+void CMsvDBAdapter::GetAllMessageIdsL(TMsvId aServiceId, RArray<TMsvId>& aIdArray,TInt32 aMtm,TMsvId lastId)
+	{
+	_LIT16(KSelectMessageId, "Select id FROM IndexEntry WHERE type = ");
+	_LIT16(KMessageMtmId," AND mtmId = ");
+	_LIT16(KSelectServiceId," AND serviceId = ");
+	_LIT16(KMessageId, " AND id > ");
+	_LIT16(KOrderByString, " order by id ASC");
+	
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(200);
+	buf.Append(KSelectMessageId);
+	buf.AppendNum(KUidMsvMessageEntryValue);
+	buf.Append(KMessageMtmId);
+	buf.AppendNum(aMtm);
+	buf.Append(KSelectServiceId);
+	buf.AppendNum(aServiceId);
+	buf.Append(KMessageId);
+	buf.AppendNum(lastId);
+	buf.Append(KOrderByString);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement Idquerystatement;
+	CleanupClosePushL(Idquerystatement);
+	User::LeaveIfError(Idquerystatement.Prepare(iDatabase, buf));
+	
+	TInt Idindex = GetColumnIndexL(Idquerystatement, KMsgColumnId());
+	
+	while(KSqlAtRow == Idquerystatement.Next())
+		{
+		aIdArray.Append(ColumnInt(Idquerystatement, Idindex));
+		}
+		
+	CleanupStack::PopAndDestroy(2);  //buf,Idquerystatement
+	}
+
+/**
+GetAllMimeIdsL()
+Gets all attachment ids for a message.
+
+@param aId: id
+@param aIdArray: Array of TMsvId.
+@retun None
+*/
+void CMsvDBAdapter::GetAllMimeIdsL(TMsvId aId, RArray<TMsvId>& aIdArray)
+	{
+	_LIT(KGetChild, "Select id, type FROM IndexEntry WHERE parentId = ");
+	
+	const TInt32 KUidMsvEmailTextEntryValue = 0x100038F1;
+	const TInt32 KUidMsvEmailHtmlEntryValue = 0x100057C0; // 268457920
+	const TInt32 KUidMsvEmailRtfEntryValue = 0x1028368F; // 271070863
+
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KGetChild);
+	buf.AppendNum(aId);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement stmt;
+	CleanupClosePushL(stmt);
+	User::LeaveIfError(stmt.Prepare(iDatabase, buf));
+	
+	TInt idIndex = 0;
+	TInt typeIndex = 1;
+		
+	// For every child..
+	while(KSqlAtRow == stmt.Next())
+		{
+		// Get the type
+		TMsvId childId = ColumnInt(stmt, idIndex);
+		TInt32 type = ColumnInt(stmt, typeIndex);
+		
+		// Append TMsvId's which may have MIME header
+		if( type == KUidMsvAttachmentEntryValue ||
+			type == KUidMsvEmailTextEntryValue ||
+			type == KUidMsvEmailHtmlEntryValue ||
+			type == KUidMsvEmailRtfEntryValue
+			)
+			{
+			aIdArray.Append(childId);
+			}
+		// Recursion for alternate folders
+		else if(type == KUidMsvFolderEntryValue)
+			{
+			aIdArray.Append(childId);
+			// also get the childs for these messages
+			GetAllMimeIdsL(childId, aIdArray);
+			}
+		}
+		
+	CleanupStack::PopAndDestroy(2); // stmt, buf
+	}
+
+/**
+GetMessageCountL()
+Gets the count of messages under a service id.
+
+@param aServiceId: service id
+*/
+TInt CMsvDBAdapter::GetMessageCountL(TMsvId aServiceId)
+	{
+	_LIT(KSelectMessageId, "Select count(*) FROM IndexEntry WHERE type = ");
+	_LIT(KServiceId," AND serviceId = ");
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KSelectMessageId);
+	buf.AppendNum(KUidMsvMessageEntryValue);
+	buf.Append(KServiceId);
+	buf.AppendNum(aServiceId);
+	buf.Append(KDelimiter);
+	
+	TSqlScalarFullSelectQuery query(iDatabase);
+	TInt msgcount = 0;
+	msgcount = query.SelectIntL(buf);
+	
+	CleanupStack::PopAndDestroy();  //buf
+	return msgcount;
+	}
+
+/**
+GetOwningServiceL()
+Gets the ids owning service.
+
+@param aId: id
+@param aOwningId: owning service id reference variable.
+@retun None
+*/
+void CMsvDBAdapter::GetOwningServiceL(TMsvId aId, TMsvId& aOwningId)
+	{
+	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
+	
+	TBool found = EFalse;
+	TMsvId entryid = aId;
+	TMsvId parentId = 0;
+	TMsvId typeId = 0;
+	
+	while (!found)
+		{
+		RBuf buf;
+		CleanupClosePushL(buf);
+		buf.CreateL(100);
+		buf.Append(KSelectServiceId);
+		buf.AppendNum(entryid);
+		buf.Append(KDelimiter);
+		
+		RSqlStatement parentIdquerystatement;
+		CleanupClosePushL(parentIdquerystatement);
+		User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
+		
+		TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
+		TInt typeIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnType());
+	
+		while(KSqlAtRow == parentIdquerystatement.Next())
+			{
+			parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
+			typeId = ColumnInt(parentIdquerystatement, typeIdindex);
+			}
+		
+		CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
+			
+		if (typeId == KUidMsvServiceEntryValue)
+			{
+			found = ETrue;
+			}
+		else
+			{
+			entryid = parentId;
+			}
+		}
+	aOwningId = entryid;
+	}
+	
+/**
+GetAllServiceIDsForMtmL()
+Gets all service ids for the specified mtm.
+
+@param aMtm: mtm id.
+@param aIdArray&: Array of TMsvId.
+@retun None
+*/
+void CMsvDBAdapter::GetAllServiceIDsForMtmL(TInt32 aMtm, RArray<TMsvId>& aIdArray)
+	{
+	// if sms, than dont get smtp id else, get the smtp id also
+	_LIT16(KSelectServiceIds, "Select distinct serviceId FROM IndexEntry where type = ");
+	_LIT16(KMtmIdQuery," AND mtmId = ");
+
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(200);
+	buf.Append(KSelectServiceIds);
+	buf.AppendNum(KUidMsvServiceEntryValue);
+	buf.Append(KMtmIdQuery);
+	buf.AppendNum(aMtm);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
+	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
+	
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
+		aIdArray.AppendL(serviceId);
+		}
+	CleanupStack::PopAndDestroy(2); //buf, stmt
+	
+	// lets also get all messages in the root with this service id
+	if(aMtm == 268439592 ) //0x1000102C sms
+		{
+		aIdArray.AppendL(KMsvGlobalOutBoxIndexEntryIdValue);	
+		aIdArray.AppendL(KMsvDraftEntryIdValue);
+		aIdArray.AppendL(KMsvSentEntryIdValue);	
+		}
+	}
+
+/**
+GetAllIndexEntryTableIdsL()
+Gets all ids present in index entry table.
+
+@param aIdArray: Array of TMsvId.
+@retun None
+*/
+void CMsvDBAdapter::GetAllIndexEntryTableIdsL(RArray<TMsvId>& aIdArray)	
+	{
+	_LIT(KSelectAllIds, "Select * FROM IndexEntry;");
+	
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
+	
+	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
+	
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
+		aIdArray.AppendL(Id);
+		}
+	CleanupStack::PopAndDestroy(); //queryStmt
+	}
+
+/**
+GetVisibleParentL()
+Gets the visible parent of the specified id.
+
+@param aId: id
+@param aVisibleParentId: visible parent id.
+@retun None
+*/
+ 
+void CMsvDBAdapter::GetVisibleParentL(TMsvId aId, TMsvId& aVisibleParentId)
+	{
+	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
+	
+	TMsvId entryid = aId;
+	TMsvId parentId = 0;
+		
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KSelectServiceId);
+	buf.AppendNum(entryid);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement parentIdquerystatement;
+	CleanupClosePushL(parentIdquerystatement);
+	
+	User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
+		
+	TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
+		
+	while(KSqlAtRow == parentIdquerystatement.Next())
+		{
+		parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
+		}
+	
+	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
+	
+	GetVisibleParentIdL(parentId,aVisibleParentId);
+	}
+
+/**
+GetVisibleParentIdL()
+This functions returns the most immediate parent visible folder id.
+There are two types of folders. A visible folder is one which is 
+visible to the external user, but there are internal non-visible folders
+created under each email message to organize the content of the email.
+Parent entry of an entry is either root or a folder. A folder can be 
+service folder (like LocalServices), userdefined folder/standard folder
+like Inbox or a non-visible folder (created under an email message).
+
+For a given parent Id, the function returns the most immediate visible
+parent folder. The rules are as follows:
+1. If the parent entry is root or children of root, then the visibleFolder 
+will be root itself. This is because service folders are considered 
+invisible, since they are not seen by user. 
+2. If the parent entry itself is a visible folder then child's visibleFolder
+id should be its parent id.
+3. If the parent entry is a non-visible folder then child's visibleFolder
+id is same as its parent's visibleFolder id.
+
+@param TMsvId: Parent Id.
+@return Most immediate visible folder id of any child entry present under passed parent id.
+*/
+void CMsvDBAdapter::GetVisibleParentIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
+	{
+	// If the entry is either a root entry (parent=KErrNotFound) or 
+	// child of root entry its visibleFolderId will be root entry itself.
+	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
+		{
+		aVisibleFolderId = KMsvRootIndexEntryId;
+		}
+	else
+		{
+		// Get the visible flag of parent entry.
+		
+		// If parent entry is visible, then immediateVisibleFolder of child
+		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
+		// should be same as parent's immediateVisibleFolder.
+		
+		//Bind the msv id
+		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
+
+		// If parent entry does not exists leave with KErrNotFound.
+		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
+			{
+			iStatement[EGetVisibleId].Reset();
+			User::Leave(KErrNotFound);
+			}
+
+		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
+		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
+			{
+			// If visible folder flag is not set for parent entry.
+			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
+			}
+		else
+			{
+			// If parent entry is visible
+			aVisibleFolderId = aParentId;
+			}
+		//Reset the RSqlStatement
+		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
+		}
+	}
+
+/**
+UpdateVisibleFolderIdL()
+Updates visible parent and any other new changes in TMsvEntry structure post PREQ 1189. 
+
+@param aId: id. 
+@param visibleId: visible parent id.
+@retun None
+*/	
+void CMsvDBAdapter::UpdateVisibleFolderIdL(TMsvId aId,TMsvId visibleId)
+	{
+	_LIT(KUpdateVisibleParentQuery,"UPDATE IndexEntry SET visibleParent = ");
+	_LIT(KWhere, " WHERE ");
+	_LIT(KUpdateVisibleParentQuery1, "id = ");
+	 	
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KUpdateVisibleParentQuery);
+	buf.AppendNum(visibleId);
+	buf.Append(KWhere);
+	buf.Append(KUpdateVisibleParentQuery1);
+	buf.AppendNum(aId);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
+	
+	TInt err = queryStmt.Exec();
+	
+	CleanupStack::PopAndDestroy(2); //stmt
+	
+	if(err < 0)
+		{
+		User::Leave(err);
+		}
+	else if(!err)
+		{
+		User::Leave(KErrGeneral);
+		}
+	}
+
+TBool CMsvDBAdapter::GetParentVisibleFlagL(TMsvId parentId)
+	{
+	_LIT(KSelectServiceId, "Select data FROM IndexEntry WHERE id = ");
+	
+	TInt data = KErrNotFound;		
+	RBuf buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KSelectServiceId);
+	buf.AppendNum(parentId);
+	buf.Append(KDelimiter);
+	
+	RSqlStatement parentDataQuerystatement;
+	CleanupClosePushL(parentDataQuerystatement);
+	
+	User::LeaveIfError(parentDataQuerystatement.Prepare(iDatabase, buf));
+		
+	TInt parentIdindex = GetColumnIndexL(parentDataQuerystatement, KMsgColumnData());
+		
+	while(KSqlAtRow == parentDataQuerystatement.Next())
+		{
+		data  = ColumnInt(parentDataQuerystatement, parentIdindex);
+		}
+	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
+	
+	return !(data & TMsvEntry::KMsvVisibleFolderNodeFlag);
+			
+	}
+	
+/**
+GetAllIndexEntryTableIdsL()
+Gets all ids present in index entry table.
+
+@param aIdArray: Array of TMsvId.
+@retun None
+*/
+void CMsvDBAdapter::GetRemainingIdsL(RArray<TMsvId>& aIdArray)	
+	{
+	_LIT(KSelectAllIds, "Select id FROM IndexEntry where visibleParent = -99;");
+	
+	RSqlStatement queryStmt;
+	CleanupClosePushL(queryStmt);
+	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
+	
+	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
+	
+	while(KSqlAtRow == queryStmt.Next())
+		{
+		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
+		aIdArray.AppendL(Id);
+		}
+	CleanupStack::PopAndDestroy(); //queryStmt
+	}
+
+/**
+DeleteTable()
+Deletes the header table identified by the UID
+
+@param aMtmId: MTM id.
+@retun None
+*/
+void CMsvDBAdapter::DeleteTableL(TUid aMtmId)	
+	{
+	_LIT16(KDropTableQuery, "DROP table if exists Header_");
+	
+	RBuf16 buf;
+	CleanupClosePushL(buf);
+	buf.CreateL(100);
+	buf.Append(KDropTableQuery);
+	buf.AppendNum(aMtmId.iUid);
+	buf.Append(KDelimiter);
+	
+	TInt err = iDatabase.Exec(buf);
+
+	CleanupStack::PopAndDestroy(); //buf
+	}
+ 
+ /**
+DeleteTable()
+Deletes the header table identified by the UID
+
+@param None
+@retun None
+*/
+void CMsvDBAdapter::DeleteSearchSortTable()	
+	{
+	_LIT16(KDropSearchSortTableQuery, "DROP table if exists SearchSortEntry;");
+	
+	TInt err = iDatabase.Exec(KDropSearchSortTableQuery);
+	}
+ 
+ 
+#endif //#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+
+