sysstatemgmt/systemstarter/dscstoresrc/dscdatabase_sql.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstarter/dscstoresrc/dscdatabase_sql.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,919 @@
+// Copyright (c) 2006-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:
+//
+
+#include "dscdatabase_sql.h"
+#include "dscitem.h"
+#include <e32debug.h>
+#include <e32math.h>
+#include <f32file.h>
+#include "e32modes.h"
+
+
+//DSC Database name
+_LIT(KDatabaseName, "%s:[2000836D]DBS_DSC.db");
+//Table name
+_LIT(KDscTable, "DSC");
+_LIT(KItemTable, "DscItem");
+//Column name
+_LIT(KDscIdCol, "DscId");
+_LIT(KDescriptionCol, "Description");
+_LIT(KItemIdCol, "ItemId");
+_LIT(KFileNameCol, "FileName");
+_LIT(KArgListCol, "ArgList");
+_LIT(KStartMethodCol, "StartMethod");
+_LIT(KTimeoutCol, "Timeout");
+_LIT(KNoOfRetriesCol, "NoOfRetries");
+_LIT(KMonitorCol, "Monitored");
+_LIT(KStartupTypeCol, "StartupType");
+_LIT(KViewlessCol, "Viewless");
+_LIT(KStartInBackgroundCol, "StartInBackground");
+
+
+_LIT8(KBeginTrans, "BEGIN");
+_LIT8(KRollbackTrans, "ROLLBACK");
+_LIT8(KCommitTrans, "COMMIT");
+
+/**
+The maximum length for DBMS varchar: 255 characters.
+@internalTechnology 
+@released
+*/
+const TInt KDscStoreMaxStringLength =255;
+
+//length of characters in TUint 32
+//This is used to calculate the length of sqlCmd in order to allocate adequate buffer.
+//characters in TUint32 and TInt32
+//This is used to calculate the length of sqlCmd in order to allocate adequate buffer.
+const TInt lengthOfTUint=10;	
+const TInt lengthOfTInt=11;
+
+//The maximum characters in DSC database name 
+const TInt KMaxDatabaseName=40;
+
+CDscDatabase* CDscDatabase::NewL()
+	{
+	CDscDatabase* db = new(ELeave) CDscDatabase();
+	CleanupStack::PushL(db);
+
+	db->ConstructL();
+
+	CleanupStack::Pop(db);
+	return db;
+	}
+
+//Second phase constructor, Open connection to Dscdatabase.
+//If DSC database doesn't exist, create it.	
+void CDscDatabase::ConstructL()
+	{
+	
+	TBuf<KMaxDatabaseName> databaseName;
+	GetDatabaseName(databaseName);
+
+ 	//Open DSC database
+ 	TInt error=iDatabase.Open(databaseName );
+
+	if (KErrNotFound!=error) //Dsc Database exists
+		{
+		//If open with error. Leave with error code return from SQLite
+		User::LeaveIfError(ConvertErrCode(error));
+		//Opened successfully
+		return;
+		}
+	
+	//DscDatabase doesn't exist
+	//Create security policy: Read: ReadDeviceData, Write: WriteDeviceData, 
+	//Schema: ReadDeviceData and WriteDeviceData
+	TSecurityPolicy defaultPolicy;
+	RSqlSecurityPolicy securityPolicy;
+	CleanupClosePushL(securityPolicy);
+	User::LeaveIfError(securityPolicy.Create(defaultPolicy));
+
+	const TSecurityPolicy KSchemePolicy(ECapabilityReadDeviceData, ECapabilityWriteDeviceData);
+	const TSecurityPolicy KReadPolicy(ECapabilityReadDeviceData);
+	const TSecurityPolicy KWritePolicy(ECapabilityWriteDeviceData);
+
+	User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy,KSchemePolicy));
+	User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy,KWritePolicy));
+	User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy,KReadPolicy));
+	
+	//Create DSC database according to security policy.
+	User::LeaveIfError(iDatabase.Create(databaseName, securityPolicy));
+
+	CleanupStack::PopAndDestroy(&securityPolicy);	
+	
+	//Create tables for DSC database	
+	TRAP(error,CreateTablesL());
+	
+	if (KErrNone > error)
+		{
+		//Fail to create tables,  destroy the DB, so next time can recreate it
+		DeleteDb();
+		}
+	User::LeaveIfError(error);
+	}	
+
+//Default constructor	
+CDscDatabase::CDscDatabase():iIsEnumOpened(EFalse)
+	{
+	}
+
+CDscDatabase::~CDscDatabase()
+	{
+	iStmt.Close();
+	iDatabase.Close();
+	}
+
+//Destroy DSC database, 
+TInt CDscDatabase::DeleteDb()
+	{
+	iDatabase.Close();
+	
+	TBuf<KMaxDatabaseName> databaseName;
+	GetDatabaseName(databaseName);
+	return iDatabase.Delete(databaseName);
+	}
+
+void CDscDatabase::CreateTablesL()
+	{
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+	//Allocate memory for create item table sql cmd which has the most characters. 
+	_LIT(KCreateItemTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S INTEGER NOT NULL, %S VARCHAR (%d)NOT NULL,\
+		 %S VARCHAR(%d), %S TINYINT, %S INTEGER, %S INTEGER, %S BIT, %S TINYINT, %S BIT, %S BIT, \
+		UNIQUE(%S, %S))");
+	//the extra characters for the %S, %d in the format string
+	const TInt extraLength=32;
+	//chars in KDscStoreMaxStringLength
+	const TInt lengthOfKDscStoreMaxStringLength=3;
+	
+	// The maximum number of characters for create table DscItem sql command		
+	const TInt length=KCreateItemTable().Length()+KItemTable().Length()+KDscIdCol().Length()+KItemIdCol().Length()+ 
+					KFileNameCol().Length()+KArgListCol().Length()+
+					KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length()+KMonitorCol().Length()+
+					KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()+
+					KDscIdCol().Length()+KItemIdCol().Length()-extraLength+2* lengthOfKDscStoreMaxStringLength;
+
+	sqlCmd.CreateL(length);					
+
+	//format a sql cmd for create table dsc
+	_LIT(KCreateDscTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S VARCHAR(%d), PRIMARY KEY(%S))");
+	sqlCmd.Format(KCreateDscTable,&KDscTable,&KDscIdCol,&KDescriptionCol, KDscStoreMaxStringLength, &KDscIdCol);
+
+
+	PrintSqlCmd(sqlCmd);
+
+	//Start a new transaction		
+	DatabaseBeginLC();
+
+	//Create Table DSC 
+	TInt error=iDatabase.Exec(sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+	
+	//Create Table DscItem	
+
+	sqlCmd.Format(KCreateItemTable,&KItemTable,&KDscIdCol, &KItemIdCol,&KFileNameCol,KDscStoreMaxStringLength,&KArgListCol,
+				KDscStoreMaxStringLength, &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,
+				&KViewlessCol, &KStartInBackgroundCol, &KDscIdCol, &KItemIdCol);
+
+	PrintSqlCmd(sqlCmd);
+
+	error=iDatabase.Exec(sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+	DatabaseCommitLP();
+	CleanupStack::PopAndDestroy(&sqlCmd);
+
+
+	
+	}
+
+#ifdef _DEBUG
+//Help, print out SQL message
+void CDscDatabase::PrintSqlCmd(const TDesC& aMess) const
+	{
+	RDebug::RawPrint(aMess);
+	}
+#else
+void CDscDatabase::PrintSqlCmd(const TDesC& /*aMess*/) const
+	{
+
+	}
+#endif
+
+//Add a DSC with aDscId to DSC DB. if the aDscId exists, leave with KErrAlreadyExists
+void CDscDatabase::CreateDscL(const TUid& aDscId, const TDesC& aDescription)
+	{
+	//If the DSC is opened for enumeration, leave with KErrLocked
+	if (iIsEnumOpened)
+		{
+		User::Leave( KErrLocked);
+		}
+		
+	//Start a new transaction		
+	DatabaseBeginLC();
+
+	//Insert aDscId in Table DSC. If aDscId exists, leave with KErrAlreadyExists	
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+	
+	_LIT(KSQLQuery,"INSERT INTO %S (%S,%S) VALUES (%d,'%S')");
+
+	//Allocate memory for insert sql cmd
+	const TInt length=KSQLQuery().Length()+ KDscTable().Length()+KDscIdCol().Length()+
+					KDescriptionCol().Length()+aDescription.Length();
+	sqlCmd.CreateL(length);
+	
+
+	sqlCmd.Format(KSQLQuery,&KDscTable,&KDscIdCol,&KDescriptionCol, aDscId, &aDescription);
+
+	PrintSqlCmd(sqlCmd);		
+	
+	TInt error=iDatabase.Exec(sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+
+	DatabaseCommitLP();	
+	}
+
+//Delete the DSC with aDscId, all items related to aDscId are deleted too.  
+void CDscDatabase::DeleteDscL(const TUid& aDscId)
+	{
+	//If the DSC is opened for enumeration, leave with KErrLocked
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}
+	
+	//Start a new transaction		
+	DatabaseBeginLC();
+	if (!DscExistsL(aDscId))
+		{
+		// aDscId doesn't exist, leave with KErrNotFound		
+		User::Leave(KErrNotFound);
+		}
+	
+	//Delete all items related with aDscId first
+	_LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d ");
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+
+	//	the extra characters for the %S, %d in the format string
+	const TInt extraLength=6;
+	//Allocate memory for delete sql cmd
+	const TInt length=KSQLQuery().Length()+ KItemTable().Length()+KDscIdCol().Length()+
+				lengthOfTUint-extraLength	;
+	sqlCmd.CreateL(length);
+	sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol,aDscId);
+	TInt error=iDatabase.Exec(sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+	
+	//Delete aDscId from Table DSC
+	sqlCmd.Format(KSQLQuery,&KDscTable,&KDscIdCol,aDscId);	
+	error=iDatabase.Exec(sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	DatabaseCommitLP();	
+	}
+
+//Check the existance of the aDscId	
+TBool CDscDatabase::DscExistsL(const TUid& aDscId) const
+	{
+
+	RSqlStatement stmt;
+	CleanupClosePushL(stmt);
+
+	_LIT(KSQLQuery,"SELECT %S FROM %S WHERE %S=%d ");
+
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+
+	//	the extra characters for the %S, %d in the format string
+	const TInt extraLength=8;
+	//Allocate memory for delete sql cmd
+	const TInt length=KSQLQuery().Length()+ KDscTable().Length()+2*KDscIdCol().Length()+
+				lengthOfTUint-extraLength	;
+	sqlCmd.CreateL(length);
+	sqlCmd.Format(KSQLQuery, &KDscIdCol, &KDscTable,&KDscIdCol,aDscId);
+
+	TInt error=stmt.Prepare(iDatabase, sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	
+	User::LeaveIfError(ConvertErrCode(error));
+	
+	error=stmt.Next();
+	User::LeaveIfError(ConvertErrCode(error));
+
+	CleanupStack::PopAndDestroy(&stmt);	
+	return KSqlAtRow==error ? ETrue:EFalse;			
+	}
+
+//Check the existance of aItem
+TBool CDscDatabase::ItemExistsL( const CDscItem& aItem) const
+	{
+
+	RSqlStatement stmt;
+	CleanupClosePushL(stmt);
+	
+	TBool result=QueryItemL(stmt, aItem);
+
+
+
+	CleanupStack::PopAndDestroy(&stmt);  
+	
+	return result;
+	}
+
+//Query the aItem from Table DscItem	
+TBool CDscDatabase::QueryItemL(RSqlStatement& aStmt, const CDscItem& aItem) const
+	{
+
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+
+
+	TUid dscId=aItem.DscId();
+	TPtrC name=aItem.FileName();
+	
+	//If fileName is NULL, query aItem by DSC ID and ItemId
+	if (name ==KNullDesC)
+		{
+		_LIT(KSQLQuery,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d AND %S=%d ");
+		//	the extra characters for the %S, %d in the format string
+		const TInt extraLength=32;
+		//Allocate memory for search sql cmd
+		const TInt length=KSQLQuery().Length()+2*KDscIdCol().Length()+KItemIdCol().Length()+ KFileNameCol().Length()
+							+KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length()
+							+KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()
+							+KItemTable().Length()+lengthOfTInt+lengthOfTUint+KItemIdCol().Length()-extraLength;
+		sqlCmd.CreateL(length);
+		sqlCmd.Format(KSQLQuery,&KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol,
+				&KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,
+				&KViewlessCol, &KStartInBackgroundCol, &KItemTable,&KDscIdCol, dscId, &KItemIdCol,aItem.ItemId());
+		}
+	//Otherwise query aItem by DSC ID, fileName and arguments	
+	else 
+		{
+		if(name.Length() >KDscStoreMaxStringLength || aItem.Args().Length() >KDscStoreMaxStringLength)
+		{
+		User::Leave(KErrArgument);
+		}
+
+		TBuf<KDscStoreMaxStringLength> argList=aItem.Args();
+		argList.TrimAll();
+		
+		_LIT(KSQLQuery,"SELECT  %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S  FROM %S WHERE %S=%d AND %S= '%S' AND %S = '%S' "); 
+		//	the extra characters for the %S, %d in the format string
+		const TInt extraLength=36;
+		//Allocate memory for search sql cmd
+		const TInt length=KSQLQuery().Length()+2*KDscIdCol().Length()+KItemIdCol().Length()+ KFileNameCol().Length()
+							+KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length()
+							+KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()
+							+KItemTable().Length()+lengthOfTUint+KFileNameCol().Length()+aItem.FileName().Length()
+						+KArgListCol().Length()+argList.Length()-extraLength;
+		sqlCmd.CreateL(length);
+		sqlCmd.Format(KSQLQuery,&KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol,	&KStartMethodCol, &KTimeoutCol,
+					 &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,&KViewlessCol, &KStartInBackgroundCol, 
+					 &KItemTable,&KDscIdCol, dscId, &KFileNameCol,&name, &KArgListCol, &argList);
+		}
+ 	
+
+	PrintSqlCmd(sqlCmd);
+
+	
+	TInt error=aStmt.Prepare(iDatabase, sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);  		
+	if(KErrNone <= error)
+		{
+		error=aStmt.Next();  //no error for non existing item
+		}
+
+	return KSqlAtRow==error? ETrue: EFalse;
+	}
+
+//Open a result set of items with aDscID for enumeration, need to 
+//call EnumClose() to close the set after enumeration.	
+void CDscDatabase::EnumOpenLC(const TUid& aDscId)
+	{
+	//If the DSC is opened for enumeration, leave with KErrLocked
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}
+	EnumBeginLC();
+	iIsEnumOpened=ETrue;
+
+	//Leave with KErrNotFound if aDscId doesn't exist
+	if (!DscExistsL(aDscId))
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+	_LIT(KSQLQuery,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d ORDER BY %S"); 
+	//	the extra characters for the %S, %d in the format string
+	const TInt extraLength=30;
+	//Allocate memory for delete sql cmd
+	const TInt length=KSQLQuery().Length()+ 2*KDscIdCol().Length()+2*KItemIdCol().Length()+ KFileNameCol().Length()
+							+KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length()
+							+KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()
+							+KItemTable().Length()+lengthOfTUint-extraLength;
+	sqlCmd.CreateL(length);
+	sqlCmd.Format(KSQLQuery, &KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol,
+				&KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,
+				&KViewlessCol, &KStartInBackgroundCol,&KItemTable,&KDscIdCol,aDscId, &KItemIdCol);
+
+
+	//Open a result stmt contains all items in aDscId
+	TInt error=iStmt.Prepare(iDatabase, sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	User::LeaveIfError(ConvertErrCode(error));
+	}
+
+//Enumrating the result stmt opened by EnumOpenLC(), if there are no item in the DSC
+//or has reached the end of the list, return NULL	
+CDscItem* CDscDatabase::EnumReadNextL()
+	{
+	if (!iIsEnumOpened)
+		{
+		//EnumOpenLC() has not been called.
+		User::Leave(KErrNotReady);
+		}
+	TInt err=iStmt.Next();
+	User::LeaveIfError(ConvertErrCode(err));	
+
+	if (KSqlAtEnd==err)
+		{
+		//reached to the end of the result set
+		return NULL;
+		}
+		
+	//Read item from the result stmt
+	CDscItem* item=CDscItem::NewL();
+	CleanupStack::PushL(item);
+	ReadDscItemL(iStmt, *item);
+	CleanupStack::Pop(item);
+	return item;
+	}	
+
+//Read aItem from the stmt
+void CDscDatabase::ReadDscItemL(RSqlStatement& aStmt, CDscItem& aItem)
+	{
+		TPtrC name=aStmt.ColumnTextL(2);
+		TPtrC args=aStmt.ColumnTextL(3);
+		aItem.SetDscId(TUid::Uid(aStmt.ColumnInt(0)));
+		aItem.SetItemId(aStmt.ColumnInt(1));
+		aItem.SetFileParamsL(name, args);
+		aItem.SetStartMethodL(static_cast<TStartMethod> (aStmt.ColumnInt(4)));
+		aItem.SetFailureParams(aStmt.ColumnInt(6), aStmt.ColumnInt(5));
+		aItem.SetMonitored(aStmt.ColumnInt(7));
+		aItem.SetStartupType(static_cast<TStartupType> (aStmt.ColumnInt(8)));
+		aItem.SetViewless(aStmt.ColumnInt(9));
+		aItem.SetStartInBackground( aStmt.ColumnInt(10));
+	}
+	
+
+//Close the view opened by EnumOpenLC() and rollback the transaction
+void CDscDatabase::EnumClose()
+	{
+	//To avoid double close
+	if (iIsEnumOpened)
+		{	
+		iStmt.Close();
+		iIsEnumOpened=EFalse;
+		
+		//Roll back transaction
+		Rollback();
+		CleanupStack::Pop();//Pop client CleanupEnumRollback	
+		}
+	}
+
+//Add aItem to DSC at aPos
+void CDscDatabase::AddItemL(CDscItem& aItem, TDscPosition aPos)
+	{
+	//Leave if DB is opened for enumeration
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}
+	
+	//verify data integrity
+	VerifyDataL(aItem);
+	
+	DatabaseBeginLC();
+
+	TUid dscId=aItem.DscId();
+	//Leave if aDscId doesn't exist
+	if (!DscExistsL(dscId))
+		{
+		User::Leave(KErrNotFound);
+		}
+	//Leave if aItem exists
+	if (ItemExistsL( aItem))
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+		
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+	//Allocate memory for insert item sql cmd which has the most characters. 
+	_LIT(KSQLQuery1,"INSERT INTO %S (%S,%S,%S,%S,%S,%S,%S,%S,%S, %S, %S ) VALUES \
+					(%d,%d,'%S','%S',%d,%d, %d, %b, %d, %b, %b)");
+	//	the extra characters for the %S, %d in the format string
+	const TInt extraLength=40;
+	const TInt length=KSQLQuery1().Length()+KItemTable().Length()+KDscIdCol().Length()+KItemIdCol().Length()
+						+KFileNameCol().Length()+KArgListCol().Length()+KStartMethodCol().Length()
+						+KTimeoutCol().Length()+KNoOfRetriesCol().Length()+KMonitorCol().Length()
+						+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()
+						+4*lengthOfTUint+ aItem.FileName().Length()+aItem.Args().Length()-extraLength;
+	sqlCmd.CreateL(length);
+	
+	RSqlStatement stmt;
+	CleanupClosePushL(stmt);
+	
+
+	//calculate item id according to the position to be inserted
+	//add at ELast: pos =max of itemId+1
+	if (ELast==aPos )
+		{
+		_LIT(KSQLQuery,"SELECT  MAX(%S) FROM %S WHERE %S=%d ");
+		sqlCmd.Format(KSQLQuery, &KItemIdCol, &KItemTable,&KDscIdCol, dscId );	
+		}	
+	//add at EFirst: pos=min of itemId-1		
+	else 
+		{
+		_LIT(KSQLQuery,"SELECT  MIN(%S) FROM %S WHERE %S=%d ");
+		sqlCmd.Format(KSQLQuery, &KItemIdCol, &KItemTable,&KDscIdCol, dscId );
+		}
+	
+
+	PrintSqlCmd(sqlCmd);
+
+
+	TInt err=stmt.Prepare(iDatabase, sqlCmd);
+	User::LeaveIfError(ConvertErrCode(err));
+	err=stmt.Next();
+	User::LeaveIfError(ConvertErrCode(err));
+	
+	//for empty DSC,  0 will be returned from the stmt, so the initial value
+	//of itemId will be -1 or 1 depend on where to insert, 
+	//this is slightly different from DBMS implementation, where 
+	//initial value for itemId is always 0
+	//Since itemId is used as reference for relative orders, this should 
+	//be acceptable
+	
+
+	//Get the next available itemId for the item
+	TInt itemId=GetItemIdL(aPos, stmt);
+
+	CleanupStack::PopAndDestroy(&stmt);
+
+	//set the item id, it will be return to client
+	aItem.SetItemId(itemId);
+	
+	//insert item into DSC
+	TPtrC name=aItem.FileName();
+	
+	//Trim white space in argment list
+	TBuf<KDscStoreMaxStringLength> argList=aItem.Args();
+	argList.TrimAll();
+
+	sqlCmd.Format(KSQLQuery1,&KItemTable,&KDscIdCol,&KItemIdCol,&KFileNameCol,&KArgListCol,
+				&KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,
+				&KViewlessCol, &KStartInBackgroundCol, dscId,itemId,&name, &argList, aItem.StartMethod(),
+				aItem.Timeout(), aItem.NoOfRetries(), aItem.Monitored(),
+				 aItem.StartupType(), aItem.Viewless(), aItem.StartInBackground());
+
+
+	PrintSqlCmd(sqlCmd);
+	
+	err=iDatabase.Exec(sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	User::LeaveIfError(ConvertErrCode(err));
+
+	DatabaseCommitLP();
+	}
+
+//Delete aItem from DSC 
+void CDscDatabase::DeleteItemL( const CDscItem& aItem)
+	{
+	//Leave if DB is opened for enumeration
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}	
+
+	DatabaseBeginLC();
+	
+	//Leave if aItem does not exist	
+	if (!ItemExistsL( aItem))
+		{
+		User::Leave(KErrNotFound);
+		}
+		
+		
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+
+
+	TPtrC name=aItem.FileName();
+	TUid dscId=aItem.DscId();
+	//Delete the item by itemId
+	if (name==KNullDesC)
+		{
+		_LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d AND %S=%d ");
+	//	the extra characters for the %S, %d in the format string
+		const TInt extraLength=10;
+		const TInt length=KSQLQuery().Length()+KItemTable().Length()+KDscIdCol().Length()+2*lengthOfTUint
+						+KItemIdCol().Length()-extraLength;
+		sqlCmd.CreateL(length);
+		
+		sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol, dscId,&KItemIdCol,aItem.ItemId());
+		}
+	//Delete the item by fileName + arguments	
+	else
+		{
+			
+		TBuf<KDscStoreMaxStringLength> argList=aItem.Args();
+		argList.TrimAll();
+		_LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d AND %S='%S' AND %S= '%S' ");
+	//	the extra characters for the %S, %d in the format string
+		const TInt extraLength=14;
+		const TInt length=KSQLQuery().Length()+KItemTable().Length()+KDscIdCol().Length()+lengthOfTUint
+						+KFileNameCol().Length()+aItem.FileName().Length()+KArgListCol().Length()
+						+aItem.Args().Length()-extraLength;
+		sqlCmd.CreateL(length);
+		
+		sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol, dscId,&KFileNameCol,&name, &KArgListCol, &argList);
+		}
+
+	PrintSqlCmd(sqlCmd);
+
+
+	TInt err=iDatabase.Exec(sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	
+	User::LeaveIfError(ConvertErrCode(err));
+	DatabaseCommitLP();
+
+	}
+	
+//Update aItem. Unable to update an item only determined by itemId
+void CDscDatabase::UpdateItemL( const CDscItem& aItem)
+	{
+	//Leave if DB is opened for enumeration	
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}
+
+	//verify data integrity,
+	VerifyDataL(aItem);
+	
+	DatabaseBeginLC();
+	//Leave if aItem does not exist
+	if (!ItemExistsL( aItem))
+		{
+		User::Leave(KErrNotFound);	
+		}
+	
+	
+	RBuf sqlCmd;
+	CleanupClosePushL(sqlCmd);
+	
+	TPtrC name=aItem.FileName();	
+
+	TBuf<KDscStoreMaxStringLength> argList=aItem.Args();
+	argList.TrimAll();
+	TUid dscId=aItem.DscId();		
+
+	//update aItem determined by fileName, argList and dscId. These three fields can't be updated		
+	_LIT(KSQLQuery,"UPDATE  %S SET %S=%d,%S=%d, %S=%d,%S=%b,%S=%d,%S=%b, %S=%b WHERE %S=%d AND %S='%S' AND %S='%S'");
+	//	the extra characters for the %S, %d in the format string 
+	const TInt extraLength=38;
+	const TInt length=KSQLQuery().Length()+KItemTable().Length()+KStartMethodCol().Length()+ KTimeoutCol().Length()
+					+3* lengthOfTUint + KNoOfRetriesCol().Length() +KMonitorCol().Length()+ KStartupTypeCol().Length()
+					+KViewlessCol().Length()+ KStartInBackgroundCol().Length()+KDscIdCol().Length()+ KFileNameCol().Length()
+					+KArgListCol().Length()+aItem.FileName().Length()+aItem.Args().Length()-extraLength;
+	sqlCmd.CreateL(length);		
+	
+	sqlCmd.Format(KSQLQuery,&KItemTable, &KStartMethodCol, aItem.StartMethod(), &KTimeoutCol, aItem.Timeout(),
+					&KNoOfRetriesCol,aItem.NoOfRetries(), &KMonitorCol, aItem.Monitored(), &KStartupTypeCol,aItem.StartupType(),
+					&KViewlessCol, aItem.Viewless(), &KStartInBackgroundCol, aItem.StartInBackground(),
+					&KDscIdCol, dscId, &KFileNameCol, &name, &KArgListCol, &argList);
+	
+
+	PrintSqlCmd(sqlCmd);
+
+		
+	TInt	err=iDatabase.Exec(sqlCmd);
+	CleanupStack::PopAndDestroy(&sqlCmd);
+	User::LeaveIfError(ConvertErrCode(err));
+	DatabaseCommitLP();
+	}
+
+//Read aItem from DSC DB either by fileName, argList and dscId, or by itemId and dscId	
+void CDscDatabase::ReadItemL(CDscItem& aItem)
+	{
+	//Leave if DB is opened for enumeration	
+	if (iIsEnumOpened)
+		{
+		User::Leave(KErrLocked);
+		}
+		
+	DatabaseBeginLC();	
+	RSqlStatement stmt;
+	CleanupClosePushL(stmt);
+	
+
+	TBool itemExists=QueryItemL(stmt, aItem);
+
+	//aItem exists
+	if(itemExists)
+		{
+		ReadDscItemL(stmt, aItem);
+		
+		//Reset all other values to default
+		aItem.SetRecoveryParams(EIgnoreOnFailure,EStartupModeUndefined);
+		aItem.SetLocalizationParamsL(KNullDesC,0);
+		}
+	//aItem does not exist
+	else
+		{
+		User::Leave(KErrNotFound);	
+		}
+	
+	CleanupStack::PopAndDestroy(&stmt);
+	DatabaseCommitLP();
+	}
+
+
+//Rollback a transaction	
+void CDscDatabase::Rollback()
+	{
+	iDatabase.Exec(KRollbackTrans);
+	}
+
+//Verify aItem
+void CDscDatabase::VerifyDataL(const CDscItem& aItem)
+	{
+	TInt noOfRetries=aItem.NoOfRetries();
+
+	//item with empty filename is not allowed to add to DB, or been updated 
+	//fileName and argList of aItem is limited to KDscStoreMaxStringLength
+	//noOfRetries is restricted to 0 or 1
+	//StartMethod is retricted to EFireAndForget or EWaitForStart
+	//Recovery policy of DscItem is restricted to IgnoreprocessFailure.	
+	if((aItem.FileName()==KNullDesC) ||(aItem.FileName().Length() > KDscStoreMaxStringLength) ||
+		(aItem.Args().Length() > KDscStoreMaxStringLength)||
+		(noOfRetries!=0 && noOfRetries!=1 ) ||(aItem.Timeout() <0) ||
+		(aItem.StartMethod() !=EFireAndForget && aItem.StartMethod() !=EWaitForStart )||
+		(aItem.RecoveryMethod() !=EIgnoreOnFailure ))
+		{
+		User::Leave(KErrArgument);
+		}
+	}
+
+//Start a new transaction.Pushes cleanup rollback action to the cleanup stack. 
+void CDscDatabase::DatabaseBeginLC()
+	{
+	TInt err=iDatabase.Exec(KBeginTrans);	
+	User::LeaveIfError(ConvertErrCode(err));
+	CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback,this));
+	
+	}
+
+//Commit transaction. Pops cleanup rollback action
+void CDscDatabase::DatabaseCommitLP()
+	{
+	TInt err=iDatabase.Exec(KCommitTrans);
+	User::LeaveIfError(ConvertErrCode(err)); // force a rollback on error
+	// Pop CleanupDatabaseRollback
+	CleanupStack::Pop();  
+	}
+
+//Cleanup rollback action for DatabaseBeginLC()	
+void CDscDatabase::CleanupDatabaseRollback(TAny *aDatabase)
+	{
+	ASSERT(aDatabase);
+	CDscDatabase* database=static_cast <CDscDatabase *>(aDatabase);
+
+	database->Rollback();
+	}
+
+//Start a new transaction for enumeration.Pushes cleanup rollback action to the cleanup stack. 
+void CDscDatabase::EnumBeginLC()
+	{
+
+	TInt err=iDatabase.Exec(KBeginTrans);
+	User::LeaveIfError(ConvertErrCode(err));
+	
+	CleanupStack::PushL(TCleanupItem(CleanupEnumRollback,this));
+	
+	}	
+//Cleanup rollback action for EnumOpenLC()
+void CDscDatabase::CleanupEnumRollback(TAny *aDatabase)
+	{
+	ASSERT(aDatabase);
+	CDscDatabase* database=static_cast <CDscDatabase *>(aDatabase);
+	database->iStmt.Close();
+	database->iIsEnumOpened=EFalse;
+		
+		//Roll back transaction
+	database->Rollback();
+	}
+
+//Covert SQLite specific error code to Symbian standard error code
+TInt CDscDatabase::ConvertErrCode(TInt aErr) const
+	{
+	if (-144<=aErr)
+		{
+		return aErr;
+		}
+	TInt err;
+	switch (aErr)
+		{
+		case KSqlErrPermission:
+			err=KErrPermissionDenied;
+			break;
+				
+		case KSqlErrBusy:
+		case KSqlErrLocked:
+			err=KErrLocked;
+			break;
+		
+		case KSqlErrCorrupt:
+			err=KErrCorrupt;
+			break;
+		
+		case KSqlErrAbort:
+			err=KErrAbort;
+			break;
+		case KSqlErrNotFound:
+			err=KErrNotFound;
+			break;
+		case KSqlErrConstraint:
+			err=KErrAlreadyExists;
+			break;
+	
+		case KSqlErrFull:
+			err=KErrOverflow;
+			break;
+					
+		default:
+			err=KErrGeneral;			
+			
+		}
+	return err;	
+	}
+
+//Get DSC database name
+void CDscDatabase::GetDatabaseNameL(TDes& aDatabaseName)
+	{
+	RFs fs;
+	CleanupClosePushL(fs);
+	User::LeaveIfError(fs.Connect());
+	//Retrieve system drive
+	TDriveNumber driveNumber=fs.GetSystemDrive();
+ 
+    TChar driveChar;
+    User::LeaveIfError(RFs::DriveToChar(driveNumber, driveChar));
+ 
+	aDatabaseName.Format(KDatabaseName,&driveChar);
+	CleanupStack::PopAndDestroy(&fs);
+	}
+//Helper function. Get the next available itemId for the item	
+TInt CDscDatabase::GetItemIdL(TDscPosition aPos, RSqlStatement& aStmt)
+	{
+	TInt itemId=aStmt.ColumnInt(0); 
+	
+	if(ELast==aPos  )
+		{
+		if(KMaxTInt32==itemId)
+			{
+			User::Leave(KErrOverflow);
+			}
+		++itemId;
+		
+		}	
+	else if(EFirst==aPos )
+		{
+		if(KMinTInt32==itemId)
+			{
+			User::Leave(KErrOverflow);
+			}
+		--itemId;
+		}
+	return itemId;		
+	}