persistentstorage/sql/SRC/Server/SqlSrvDatabase.cpp
changeset 0 08ec8eefde2f
child 9 667e88a979d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvDatabase.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1626 @@
+// Copyright (c) 2005-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 "SqlSrvFileData.h"		//TSqlSrvFileData
+#include "SqlSrvMain.h"			//CSqlServer
+#include "SqlSrvAuthorizer.h"	//MSqlPolicyInspector
+#include "SqlSrvDatabase.h"
+#include "SqlSrvStatement.h"
+#include "SqlUtil.h"			//Panic codes, Sql2OsErrCode()
+#include "SqlSrvUtil.h"			//Global server functions
+#include "SqlCompact.h"
+#include "SqlSrvResourceProfiler.h"
+
+//
+// The following macro disables the creation/loading of the settings table.
+// It is for internal testing purposes only!
+// 
+//    __SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__
+// 
+// This means that the database index will always be rebuilt when loaded by 
+// by the server regardless of the current system collation/locale in use. 
+// The benefit of enabling this macro is that a client can send PRAGMA 
+// commands to the SQL server before any tables have been explicity created in 
+// a NON-SECURE database (secure databases still automatically get a security 
+// policy table).
+//
+// The macro is applied inside:  
+//		CSqlSrvDatabase::StoreSettingsL
+// 		CSqlSrvDatabase::ProcessSettingsL
+// 
+// We should inform the user at compile-time if this macro has been enabled:
+#if defined(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)
+#pragma message(">>> WARNING: Use of SYMBIAN_SETTINGS table has been disabled <<<")
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////        Local const data   ///////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const char* KErrMsg1 = "Missing ESCAPE expression";
+const char* KErrMsg2 = "ESCAPE expression must be a single character";
+
+////////////////////////////////////////////////////////
+//Attach/detach SQL statements (zero-terminated strings)
+_LIT(KAttachDb, "ATTACH DATABASE :FileName AS :DbName\x0");
+_LIT(KDetachDb, "DETACH DATABASE :DbName\x0");
+////////////////////////////////////////////////////////
+// Pragma SQL statements. The database names in all statements are quoted to avoid the "sql injection" threat.
+// (At the moment there is no way to pass an invalid database name for these statements, because the database has to be attached
+//  first and a parameter binding is used there. So, the quoting is just for safety and against changes in the future)
+_LIT(KCacheSizePragma,	"PRAGMA \"%S\".cache_size=%d\x0");
+_LIT(KPageSizePragma,	"PRAGMA \"%S\".page_size=%d\x0");
+_LIT(KAutoVacuumPragma,	"PRAGMA \"%S\".auto_vacuum=%d\x0");
+//_LIT(KPersist, "persist");
+//_LIT(KPersistentJournalPragma, "PRAGMA \"%S\".journal_mode=%S\x0");
+////////////////////////////////////////////////////////
+//"LIKE" - user defined function name
+_LIT8(KStrLikeFuncName,  "LIKE\x0");
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////        Local functions    ///////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//Local function, used for comparing TSqlAttachDbPair objects.
+//(TSqlAttachDbPair structure represents type of the objects, members
+// of the map used for keeping the information regarding attached databases)
+//
+//Note that iKey members of aLeft and aRight function parameters are expected to be 
+//UTF8 encoded, zero-terminated strings.
+//
+//The function will panic with panic code 7 in _DEBUG mode if iKey member of aLeft or
+//aRight argument is NULL.
+static TInt Compare(const TSqlAttachDbPair& aLeft, const TSqlAttachDbPair& aRight)
+	{
+	__SQLASSERT(aLeft.iKey != NULL && aRight.iKey != NULL, ESqlPanicInternalError);
+	return ::CompareNoCase8(TPtrC8(aLeft.iKey), TPtrC8(aRight.iKey));
+	}
+
+//Local function, used for comparing TSqlCompactDbPair objects.
+//(TSqlCompactDbPair structure represents type of the objects, members
+// of the map used for keeping the information regarding compacted databases)
+//
+//Note that iKey members of aLeft and aRight function parameters are expected to be 
+//UTF16 encoded strings.
+//
+//The function will panic with panic code 7 in _DEBUG mode if iKey member of aLeft or
+//aRight argument is NULL.
+static TInt Compare2(const TSqlCompactDbPair& aLeft, const TSqlCompactDbPair& aRight)
+	{
+	__SQLASSERT(aLeft.iKey != NULL && aRight.iKey != NULL, ESqlPanicInternalError);
+	return ::CompareNoCase(*aLeft.iKey, *aRight.iKey);
+	}
+
+//Creates/opens database file (database file name in aFileData parameter) and initializes aDbHandle parameter.
+//The database will be created either with UTF-16 or UTF-8 encoding, depending on the 
+//TSqlSrvFileData::IsUTF16() property.
+static void CreateDbHandleL(const TSqlSrvFileData& aFileData, sqlite3*& aDbHandle)
+	{
+	if(aFileData.ConfigParams().iDbEncoding == TSqlSrvConfigParams::EEncUtf8)
+		{
+		TBuf8<KMaxFileName + 1> fileNameZ;
+		if(!::UTF16ZToUTF8Z(aFileData.FileNameZ(), fileNameZ))
+			{
+			__SQLLEAVE(KErrGeneral);	
+			}
+		__SQLLEAVE_IF_ERROR(::CreateDbHandle8(fileNameZ, aDbHandle));
+		}
+	else
+		{
+		__SQLLEAVE_IF_ERROR(::CreateDbHandle16(aFileData.FileNameZ(), aDbHandle));
+		}
+	}
+	
+//LoadAttachedDbSecurityPolicyLC() creates a new CSqlSecurityPolicy object and initializes it with the 
+//security policies read from the attached database file, which name is in aFileData parameter.
+//The created database security policy object is placed in the cleanup stack.
+//The caller is responsible for the destruction of the created and returned security policy object.
+//This function is used to read the security policies of attached databases.
+static CSqlSecurityPolicy* LoadAttachedDbSecurityPolicyLC(const TSqlSrvFileData& aFileData)
+	{
+	//Create new database security policy object and initialize it with a default security policy
+	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
+	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
+	//This is an attached  database and has to be opened
+	sqlite3* dbHandle = NULL;
+	CreateDbHandleL(aFileData, dbHandle);
+	CleanupStack::PushL(TCleanupItem(&CloseDbCleanup, dbHandle));
+	//Read the security policies.
+	TSqlDbSysSettings dbSysSettings(dbHandle);
+	dbSysSettings.LoadSecurityPolicyL(*dbPolicy);
+	CleanupStack::PopAndDestroy();//TCleanupItem(&CloseDbCleanup, dbHandle)
+	return dbPolicy;
+	}
+
+//LoadDbSecurityPolicyLC() creates a new CSqlSecurityPolicy object and initializes it with the 
+//security policies read from the database file.
+//The created database security policy object is placed in the cleanup stack.
+//The caller is responsible for destroying the returned database security policy object.
+//The function is used to read the security policy of the main database.
+static CSqlSecurityPolicy* LoadDbSecurityPolicyLC(sqlite3* aDbHandle)
+	{
+	__SQLASSERT(aDbHandle != NULL, ESqlPanicBadArgument);
+	//Create new database security policy object and initialize it with a default security policy
+	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
+	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
+	//Read the security policies.
+	TSqlDbSysSettings dbSysSettings(aDbHandle);
+	dbSysSettings.LoadSecurityPolicyL(*dbPolicy);
+	return dbPolicy;
+	}
+
+//CreateStrCopyLC() makes a copy of aSrc string and places it in the cleanup stack.
+//aSrc is expected to be UTF8 encoded, zero terminated string.
+//The function panics in _DEBUG mode if aSrc is NULL.
+static TUint8* CreateStrCopyLC(const TUint8* aSrc)
+	{
+	__SQLASSERT(aSrc != NULL, ESqlPanicBadArgument);
+	TInt len = User::StringLength(aSrc) + 1;
+	TUint8* copy = new (ELeave) TUint8[len];
+	Mem::Copy(copy, aSrc, len);
+	CleanupStack::PushL(copy);
+	return copy;
+	}
+
+//EnableAuthorizer() function is used to reenable the authorizer callback
+//during the stack cleanup.
+static void EnableAuthorizer(void* aAuthorizerDisabled)
+	{
+	__SQLASSERT(aAuthorizerDisabled != NULL, ESqlPanicBadArgument);
+	TBool* authorizerDisabled = static_cast <TBool*> (aAuthorizerDisabled);
+	*authorizerDisabled = EFalse;
+	}
+
+//Used by DbFileCleanup()
+NONSHARABLE_STRUCT(TDbFileCleanup)
+	{
+	TDbFileCleanup(const TSqlSrvFileData& aSqlSrvFileData, sqlite3*& aDbHandle) :
+		iSqlSrvFileData(aSqlSrvFileData),
+		iDbHandle(aDbHandle)
+		{
+		//aDbHandle can be NULL (it is a reference to a pointer and the pointer can be initialized later)
+		}
+	void Cleanup()
+		{
+		::CloseDbHandle(iDbHandle);//This operation also deletes the journal file
+		iDbHandle = NULL;
+		(void)iSqlSrvFileData.Fs().Delete(iSqlSrvFileData.FileName());
+		}
+private:
+	const TSqlSrvFileData&	iSqlSrvFileData;
+	sqlite3*& 				iDbHandle;
+	};
+
+//DbFileCleanup() is used to close and delete the database file during the stack cleanup, if
+//CSqlSrvDatabase's ConstructL() method(s) leave (when creating a new database file).
+static void DbFileCleanup(void* aDbFileCleanup)
+	{
+	__SQLASSERT(aDbFileCleanup != NULL, ESqlPanicBadArgument);
+	TDbFileCleanup* dbFileCleanup = static_cast <TDbFileCleanup*> (aDbFileCleanup);
+	dbFileCleanup->Cleanup();
+	}
+
+//Executes "PRAGMA" SQL statement + INTEGER value.
+//Pragma parameters:
+// aValue - integer pragma value to be set;
+// aPragma - pragma statement, the format is: ""PRAGMA <database name>.<parameter name>=%d\x0""
+// aDbName - "main" or the attached database name
+//This function is used for setting "cache_size", "page_size", "auto_vacuum" pragmas.
+//During the call the authorizer will be disabled.
+static TInt ExecPragma(sqlite3* aDbHandle, TBool& aAuthorizerDisabled, const TDesC& aPragma, TInt aValue, const TDesC& aDbName = KMainDb16)
+	{
+	__SQLASSERT(aDbHandle != NULL, ESqlPanicBadArgument);
+	TBuf<KMaxFileName + 64> pragmaSql;//(KMaxFileName + 64) characters buffer length is enough for the longest possible PRAGMA statement
+	pragmaSql.Format(aPragma, &aDbName, aValue);
+	TBool authorizerDisabledState = aAuthorizerDisabled;
+	aAuthorizerDisabled	= ETrue;
+	TInt err = DbExecStmt16(aDbHandle, pragmaSql);
+	aAuthorizerDisabled = authorizerDisabledState;
+	return err;
+	}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////   CSqlSrvDatabase class    /////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+/////////////////////////////   Object creation methods  /////////////////////////////////////////////
+
+/**
+Creates new CSqlSrvDatabase instance which creates and manages new secure SQL database.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 The format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 "[SID]" refers to SID of the application which creates the database.
+@param aSecurityPolicy The database security policies container. 
+					   CSqlSrvDatabase instance stores the pointer in the security policy map,
+					   if it does not exist there already. The security policies map is owned by the CSqlServer class.
+
+@return A pointer to the created CSqlSrvDatabase instance.
+
+@see CSqlServer
+@see TSqlSrvFileData
+@see MSqlPolicyInspector
+@see RSqlSecurityMap
+@see CSqlSecurityPolicy
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KErrArgument, if a system table name found in the security policies (aSecurityPolicy);
+	   KErrAlreadyExists, the file already exists;
+       KErrNotReady, the drive does not exist or is not ready;
+       KErrInUse, the file is already open;
+       KErrPermissionDenied, the client application does not satisfy the relevant database security policies.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+                      
+@panic SqlDb 4 In _DEBUG mode if aFileData does not refer to a secure database file name.
+@panic SqlDb 4 In _DEBUG mode if aSecurityPolicy is NULL.
+*/
+CSqlSrvDatabase* CSqlSrvDatabase::CreateSecureL(const TSqlSrvFileData& aFileData, CSqlSecurityPolicy* aSecurityPolicy)
+	{
+	__SQLASSERT(aFileData.IsSecureFileNameFmt(), ESqlPanicBadArgument);
+	__SQLASSERT(aSecurityPolicy != NULL, ESqlPanicBadArgument);
+	if(!::SqlServer().SecurityInspector().Check(aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::ESchemaPolicy)))
+		{
+		//The caller has no "SCHEMA" policy. Then the client is not given a permission to create the database.
+		//Delete aSecurityPolicy since no database object is going to be created and the security policy object 
+		//won't be put in the security policies map.
+		delete aSecurityPolicy;
+		__SQLLEAVE(KErrPermissionDenied);
+		}
+	//What does happen with aSecurityPolicy instance?
+	// If the database is created successfully, then a lookup will be made in the security policies map.
+	// (the security policies map contains reference counted security policies)
+	//    If the same security policy already exists in the map, then aSecurityPolicy will be deleted.
+	//                                          The reference counter of the found policy will be incremented.
+	//    If aSecurityPolicy is not in the map, then it will be put in the map and removed
+	//                                          from the map when CSqlSrvDatabase object is destroyed.
+	//											(the "remove" operation decrements the security policy counter
+	//											and destroys the policy if it reaches 0)
+	//
+	//The security policy map pair is:
+	//{secure_db_name, reference_counted db_security_policy}
+	//The security policy is reference counted, because the same database can be shared between one or more
+	//connections (clients), in which case only a single, reference counted instance of the database security
+	//policy is kept in the map.
+	CleanupStack::PushL(aSecurityPolicy);
+	CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
+	CleanupStack::Pop(aSecurityPolicy);
+	CleanupStack::PushL(self);
+	self->ConstructCreateSecureL(aFileData, aSecurityPolicy);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Creates new CSqlSrvDatabase instance which creates and manages new SQL database.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+
+@return A pointer to the created CSqlSrvDatabase instance.
+
+@see CSqlServer
+@see TSqlSrvFileData
+@see MSqlPolicyInspector
+@see RSqlSecurityMap
+@see CSqlSecurityPolicy
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KErrArgument, the file name is a name of a secure database;
+	   KErrAlreadyExists, the file already exists;
+       KErrNotReady, the drive does not exist or is not ready;
+       KErrInUse, the file is already open;
+       KErrArgument, the file name refers to a secure database, but aSecurityPolicy is NULL;
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@panic SqlDb 4 In _DEBUG mode if aFileData refers to a secure database file name.
+*/
+CSqlSrvDatabase* CSqlSrvDatabase::CreateL(const TSqlSrvFileData& aFileData)
+	{
+	__SQLASSERT(!aFileData.IsSecureFileNameFmt(), ESqlPanicBadArgument);
+	CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
+	CleanupStack::PushL(self);
+	self->ConstructCreateL(aFileData);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Creates new CSqlSrvDatabase instance which opens and manages an existing SQL database.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which created the database.
+				 If this is application's private database, then the format of aFileData is as it is described
+				 in TSqlSrvFileData::SetFromHandleL() comments.
+
+@return A pointer to the created CSqlSrvDatabase instance.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+       KErrNotReady, the drive does not exist or is not ready;
+       KErrNotFound, the database file does not exist;
+       KErrInUse, the file is already open;
+       KErrPermissionDenied, the client application does not satisfy the relevant database security policies.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see CSqlServer
+@see TSqlSrvFileData
+@see MSqlPolicyInspector
+@see RSqlSecurityMap
+@see CSqlSecurityPolicy
+@see TSqlSrvFileData::SetFromHandleL()
+*/
+CSqlSrvDatabase* CSqlSrvDatabase::OpenL(const TSqlSrvFileData& aFileData)
+	{
+	CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
+	CleanupStack::PushL(self);
+	aFileData.IsSecureFileNameFmt() ? self->ConstructOpenSecureL(aFileData) : self->ConstructOpenL(aFileData);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Cleans up the allocated for the database connection memory and other resources.
+*/
+CSqlSrvDatabase::~CSqlSrvDatabase()
+	{
+    SQLPROFILER_DB_CLOSE((TUint)iDbHandle);
+	TSqlCompactDbMapIterator compactDbIt(iCompactDbMap);
+	TSqlCompactDbPair compactDbPair;
+	while(compactDbIt.Next(compactDbPair))
+		{
+		::SqlServer().Compactor().ReleaseEntry(*compactDbPair.iData);
+		}
+	iCompactDbMap.Close();
+	//If iSecureDbName is not NULL, the current CSqlSrvDatabase object operates on a secure database.
+	//The database security policy has to be removed from the security policy map.
+	//(The "remove" operation actually decrements the security policy reference counter and destroys the policy
+	//when the counter reaches 0. The counter value may be greater than 1 if the database is shared between
+	//more than one connection)
+	if(iSecureDbName)
+		{
+		::SqlServer().SecurityMap().Remove(iSecureDbName);
+		//The security policy map owns iSecureDbName and iSecurityPolicy and is responsible for 
+		//iSecureDbName and iSecurityPolicy destruction.
+		}
+	iAttachDbMap.Close();
+	::CloseDbHandle(iDbHandle);
+	}
+
+/**
+Initializes CSqlSrvDatabase data memebers with their default values.
+
+
+@see MSqlPolicyInspector
+@see RSqlSecurityMap
+@see CSqlServer
+*/
+CSqlSrvDatabase::CSqlSrvDatabase() :
+	iAttachDbMap(TSqlAttachDbLinearOrder(&Compare), TSqlAttachDbDestructor()),
+	iCompactDbMap(TSqlCompactDbLinearOrder(&Compare2), TSqlCompactDbDestructor())
+	{
+	}
+	
+/**
+Creates a new SQL database file and executes config pragmas.
+This function is part of CSqlSrvDatabase instance initialization.
+If the function leaves and the error is not KErrAlreadyExists, the database file will be deleted.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+
+@see TSqlSrvFileData
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+       KErrAlreadyExists, the file already exists.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+*/
+void CSqlSrvDatabase::CreateNewDbFileL(const TSqlSrvFileData& aFileData)
+	{
+	if(::FileExists(aFileData.Fs(), aFileData.FileName()))
+		{
+		__SQLLEAVE(KErrAlreadyExists);	
+		}		
+	TDbFileCleanup dbFileCleanup(aFileData, iDbHandle);
+	CleanupStack::PushL(TCleanupItem(&DbFileCleanup, &dbFileCleanup));
+	::CreateDbHandleL(aFileData, iDbHandle);
+	SetConfigL(aFileData.ConfigParams(), ETrue);
+	CleanupStack::Pop();//DbFileCleanup
+	}
+	
+/**
+Opens an existing SQL database file and executes config pragmas.
+
+This function is part of CSqlSrvDatabase instance initialization.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+				 If this is application's private database, then the format of aFileData is as it is described
+				 in TSqlSrvFileData::SetFromHandleL() comments.
+				
+@leave KErrNoMemory, an out of memory condition has occurred;
+       KErrNotFound, SQL database file not found.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see TSqlSrvFileData
+@see TSqlSrvFileData::SetFromHandleL()
+*/
+void CSqlSrvDatabase::OpenExistingDbFileL(const TSqlSrvFileData& aFileData)
+	{
+	if(!aFileData.ContainHandles())
+		{//This check is valid only if the database is outside application's private data cage
+		if(!::FileExists(aFileData.Fs(), aFileData.FileName()))
+			{
+			__SQLLEAVE(KErrNotFound);	
+			}
+		}
+	::CreateDbHandleL(aFileData, iDbHandle);
+	//this is an existing database, only the cache size can be changed, the page size is persistent database property.
+	//But for private databases, opened on the client side - the page size can be set (for the "create database" operations).
+	SetConfigL(aFileData.ConfigParams(), aFileData.ContainHandles());
+	}
+	
+/**
+Installs an authorizer callback function.
+
+The callback function is invoked by the SQL parser at SQL statement compile time for each attempt 
+to access a column of a table in the database and is used to assert the calling application's rights to
+perform specific SQL operation.
+
+This function is part of CSqlSrvDatabase instance initialization.
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError.
+*/
+void CSqlSrvDatabase::InstallAuthorizerL()
+	{
+	//Install the authorizer just once. "Install authorizer" may be expensive and dangerous operation because 
+	//it will expire the already prepared statements.
+	if(!iAuthorizerInstalled)
+		{
+		(void)sqlite3SymbianLastOsError();//clear last OS error
+		TInt err = sqlite3_set_authorizer(iDbHandle, &CSqlSrvDatabase::AuthorizeCallback, this);
+		__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+		}
+	iAuthorizerInstalled = ETrue;
+	}
+
+#ifdef SYMBIAN_USE_SQLITE_VERSION_3_6_4
+extern "C" int sqlite3RegisterInternalUtf8Like(sqlite3 *db);
+#endif
+/**
+Installs user-defined functions. At the moment there is only one: LIKE.
+
+Replacing the LIKE operator default implementation with user defined LIKE functions.
+The default implementation need a replacement because it does not work correctly with UTF16 encoded strings.
+*/
+void CSqlSrvDatabase::InstallUDFsL()
+	{
+	//Registering user defined LIKE function with 2 parameters for UTF16 encoding
+	TInt err = sqlite3_create_function(iDbHandle, reinterpret_cast <const char*> (KStrLikeFuncName().Ptr()),
+									   2/*arg*/, SQLITE_UTF16, this /*user data*/, 
+									   &CSqlSrvDatabase::LikeSqlFunc, NULL/*xStep*/, NULL/*xFinal*/);
+	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+	//Registering user defined LIKE function with 3 parameters for UTF16 encoding 
+	err = sqlite3_create_function(iDbHandle, reinterpret_cast <const char*> (KStrLikeFuncName().Ptr()),
+								  3/*arg*/, SQLITE_UTF16, this/*user data*/, 
+								  &CSqlSrvDatabase::LikeSqlFunc, NULL/*xStep*/, NULL/*xFinal*/);
+	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+	
+#ifdef SYMBIAN_USE_SQLITE_VERSION_3_6_4
+	//Registering user defined LIKE function with 2 and 3 parameters for UTF8 encoding
+	//Once registered, these will be treated as built-in functions 
+	err = sqlite3RegisterInternalUtf8Like(iDbHandle);
+	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+#endif
+	}
+
+/**
+Constructs a key for searching in the security policies map.
+
+The key is UTF8 encoded, zero-terminated string.
+
+Every time when CSqlSrvDatabase instance creates, opens or attaches a secure database, it updates
+the contents of the security policies map (RSqlSecurityMap class), which is a single instance owned 
+by the CSqlServer class.
+
+@param aDbFileName Full secure database file name, from which the security policies map key 
+				   will be constructed.
+
+@return A const pointer to the constructed security map key. No memory is allocated for the key.
+
+@leave KErrGeneral the UTF16 to UTF8 conversion of aDbFileName parameter failed.
+
+@see RSqlSecurityMap
+@see CSqlServer
+*/
+const TUint8* CSqlSrvDatabase::SecurityMapKeyL(const TDesC& aDbFileName)
+	{
+	//Form the map item key - the secure database name
+	TParsePtrC parse(aDbFileName);//this call may panic if aDbFileName cannot be parsed. But aDbFileName was preprocessed by TSqlSrvFileData::Set
+	TFileName secureDbName;
+	secureDbName.Copy(parse.Drive());
+	secureDbName.Append(parse.NameAndExt());
+	secureDbName.Append(TChar(0));
+	TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
+	if(!::UTF16ZToUTF8Z(secureDbName, ptr))
+		{
+		__SQLLEAVE(KErrGeneral);			
+		}
+	return iFileNameBuf;
+	}
+
+/**
+Attaches a secure or non-secure database to the current database connection.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+@param aDbName Database name. It must be unique (per database connection). This is the name which can
+               be used for accessing tables in the attached database. The syntax is "database-name.table-name".
+
+@leave KErrNotFound, the database file which has to be attached does not exist.
+       KErrPermissionDenied, the client application does not satisfy the relevant security policies of
+       				  the attached database.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see TSqlSrvFileData
+*/
+void CSqlSrvDatabase::AttachDbL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
+	{
+	if(!aFileData.ContainHandles())
+		{//This check is valid only if the database is outside application's private data cage
+		if(!::FileExists(aFileData.Fs(), aFileData.FileName()))
+			{
+			__SQLLEAVE(KErrNotFound);	
+			}
+		}
+	if(!aFileData.IsSecureFileNameFmt())		
+		{//A non-secure database to be attached -  execute the "ATTACH DB" SQL statement and initialize the attached database.
+		InitAttachedDbL(aFileData, aDbName);
+		}
+	else
+		{//A secure database has to be attached. This is a complex operation and if it fails, proper cleanup
+		 //has to be performed. "state" variable keeps the state, after which the "attach db" operation failed.
+		 //There are three things needed to be done when atatching a secure database:
+		 // 1. Executing the "ATTACH DB" SQL statement and initializing the attached database
+		 // 2. Updating the security policy map
+		 // 3. Updating the {db name, logical db name} map
+		 //The additional map (3) is needed because when the authorizer callback is called by SQLITE, the callback
+		 //is given the logical database name, if that's an operation on an attached database. Since the security 
+		 //policy map uses the database name as a key, the map (3) is used to find what is the physical database 
+		 //name, which the logical database name points to.
+		 //
+		 //There is an additional step (0), which may happen when a secure database is attached to a 
+		 //non-secure database. But this step does not require a cleanup.
+		CSqlSrvDatabase::TAttachState state = CSqlSrvDatabase::EAStNone;
+		const TUint8* securityMapKey = NULL;
+		TRAPD(err, DoAttachSecureDbL(state, aFileData, aDbName, securityMapKey));
+		if(err != KErrNone)
+			{
+			//Cleanup
+			if(state > CSqlSrvDatabase::EAStNone)
+				{
+				(void)FinalizeAttachedDb(aDbName);
+				if(state > CSqlSrvDatabase::EAStDbAttached)
+					{
+					::SqlServer().SecurityMap().Remove(securityMapKey);
+					}
+				}
+			__SQLLEAVE(err);
+			}
+		}
+	}
+
+/**
+Attaches a secure database to the existing connection.
+
+The function also updates the following maps:
+- Security policies map (CSqlServer::iSecurityMap), where a reference counted copy of database security policies
+  is kept for each created/opened/attached database during the life time of the SQL server;
+- Attached secure databases map (CSqlSrvDatabase::iAttachDbMap), where an information is kept what SQL database
+  file name corresponds to a specific attached database name. This information is used by the authorizer callback
+  function in order to find what database security policies have to be asserted when a SQL operation is issued
+  for a particular attached database (the attached database name is identified always by its name, not the file name);
+
+@param aState Output parameter - the attach progress state, used by the calling function to perform correctly 
+			  the cleanup, if the attach operation fails.
+			  It may have the following values set:
+			  - CSqlSrvDatabase::EAStNone - no resources need to be freed;
+			  - CSqlSrvDatabase::EAStDbAttached - the function was able to execute the "ATTACH DATABASE"
+			      SQL statement before an error occured. The calling function has to execute "DETACH DATABASE"
+			      SQL statement to detach the database;
+			  - CSqlSrvDatabase::EAStSecurityMapUpdated - the function was able to update the security policies
+			      map (CSqlServer::iSecurityMap) before an error occured. The calling function has to remove
+			      the attached database security policies from the map and detach the database.
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 The secure database name format must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 "[SID]" refers to SID of the application which creates the database.
+@param aDbName Database name. It must be unique (per database connection). This is the name which can
+               be used for accessing tables in the attached database. The syntax is "database-name.table-name".
+@param aMapKey Output parameter, UTF8 encoded, zero-terminated string, which can be used for searching 
+			   of the attached database security policies in the security policies map (CSqlServer::iSecurityMap). 
+			   No memory is allocated for the key.
+
+@see RSqlSecurityMap
+@see RSqlAttachDbMap
+@see CSqlServer
+@see TSqlSrvFileData
+@see CSqlSrvDatabase
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+       KErrPermissionDenied, the client application does not satisfy the relevant security policies of
+       				  the attached database.
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+*/
+void CSqlSrvDatabase::DoAttachSecureDbL(CSqlSrvDatabase::TAttachState& aState, 
+										const TSqlSrvFileData& aFileData, 
+										const TDesC& aDbName, const TUint8*& aMapKey)
+	{
+	//Step 1: Attach the database and initialize the attached database
+	InitAttachedDbL(aFileData, aDbName);
+	aState = CSqlSrvDatabase::EAStDbAttached;
+	//Step 2: Load the database security policy and update the security map
+	const CSqlSecurityPolicy* securityPolicy = NULL;
+	UpdateSecurityMapL(ETrue, aFileData, aMapKey, securityPolicy);
+	aState = CSqlSrvDatabase::EAStSecurityMapUpdated;
+	//Check that the caller has at least one of {Schema, Read, Write} policies.
+	BasicSecurityPolicyCheckL(*securityPolicy);
+	//Step 3: Update the attached databases map
+	InsertInAttachDbMapL(aFileData.FileName(), aDbName);
+	}
+	
+/**
+Detaches a database from the current database connection.
+
+The function also will search the security policies map (CSqlServer::iSecurityMap) and the attached databases
+map (CSqlSrvDatabase::iAttachDbMap) for entries which correspond to the database ,
+which is about to be detached, and will remove the entries.
+
+@param aDbName Attached database name. It must be unique (per database connection).
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError, 
+	   and other system-wide error codes.
+	   
+@see CSqlSrvDatabase::DoAttachSecureDbL()
+@see RSqlSecurityMap
+@see RSqlAttachDbMap
+@see CSqlServer
+@see CSqlSrvDatabase
+*/
+void CSqlSrvDatabase::DetachDbL(const TDesC& aDbName)
+	{
+	TInt err = FinalizeAttachedDb(aDbName);
+	if(err == KErrNone)
+		{
+		TRAP(err, RemoveFromMapsL(aDbName));//ignore the error
+		}
+	else
+		{
+		__SQLLEAVE(err);
+		}
+	}
+
+/**
+Calculates and returns the database size. 
+
+@param aDbName Attached database name or KNullDesC for the main database
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError, 
+	   and other system-wide error codes.
+
+@return Database size in bytes.
+*/
+TInt64 CSqlSrvDatabase::SizeL(const TDesC& aDbName)
+	{
+	iAuthorizerDisabled	= ETrue;
+	CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+	TInt pageCount = 0;
+	__SQLLEAVE_IF_ERROR(::DbPageCount(iDbHandle, aDbName, pageCount));
+	__SQLASSERT(pageCount >= 0, ESqlPanicInternalError);
+	CleanupStack::PopAndDestroy();
+	return (TInt64)pageCount * PageSizeL(aDbName);
+	}
+
+/**
+Retrieves the database free space. 
+
+@param aDbName Attached database name or KNullDesC for the main database
+
+@return Database free space in bytes.
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError, 
+	   and other system-wide error codes.
+*/
+TInt64 CSqlSrvDatabase::FreeSpaceL(const TDesC& aDbName)
+	{
+	iAuthorizerDisabled	= ETrue;
+	CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+	TInt freePageCount = 0;
+	__SQLLEAVE_IF_ERROR(::DbFreePageCount(iDbHandle, aDbName, freePageCount));
+	CleanupStack::PopAndDestroy();
+	__SQLASSERT(freePageCount >= 0, ESqlPanicInternalError);
+	return (TInt64)freePageCount * PageSizeL(aDbName);
+	}
+
+/**
+Collects information regarding the current cache size, page, size, encoding, etc. and puts the values
+in the aDest output string.
+
+@param aDest Output parameter, where the result values will be stored. The string format is: "<val1>;<val2>...;".
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError, 
+	   and other system-wide error codes.
+*/
+void CSqlSrvDatabase::QueryConfigL(TDes8& aDest)
+	{
+	iAuthorizerDisabled	= ETrue;
+	CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+
+	TInt cacheSize = 0;
+	__SQLLEAVE_IF_ERROR(::DbCacheSize(iDbHandle, KNullDesC, cacheSize));
+	
+	TInt pageSize = 0;
+	__SQLLEAVE_IF_ERROR(::DbPageSize(iDbHandle, KNullDesC, pageSize));
+
+	TBuf8<16> encoding;
+	__SQLLEAVE_IF_ERROR(::DbEncoding(iDbHandle, KNullDesC, encoding));
+
+	TInt defaultSoftHeapLimit = TSqlSrvConfigParams::KDefaultSoftHeapLimitKb;
+
+	TInt vacuum = 0;
+	__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, KNullDesC, vacuum));
+
+	aDest.AppendNum(cacheSize);	
+	_LIT8(KSemiColon, ";");
+	aDest.Append(KSemiColon);	
+	aDest.AppendNum(pageSize);	
+	aDest.Append(KSemiColon);	
+	aDest.Append(encoding);	
+	aDest.Append(KSemiColon);	
+	aDest.AppendNum(defaultSoftHeapLimit);	
+	aDest.Append(KSemiColon);	
+	aDest.AppendNum(vacuum);	
+	aDest.Append(KSemiColon);	
+	
+	CleanupStack::PopAndDestroy();
+	}
+
+/**
+Compacts the database free space. 
+
+@param aSize The requested database space to be compacted, in bytes.
+			 If aSize value is RSqlDatabase::EMaxCompaction, then all free pages will be removed.
+			 Note that the requested space to be compacted will be rounded up to the nearest page count,
+			 e.g. request for removing 1 byte will remove one free page from the database file. 
+
+@param aDbName Attached database name or KNullDesC for the main database
+
+@return The size of the removed free space
+
+@leave The function may leave with some database specific errors categorised as ESqlDbError, 
+	   and other system-wide error codes.
+*/
+TInt CSqlSrvDatabase::CompactL(TInt aSize, const TDesC& aDbName)
+	{
+	__SQLASSERT(aSize > 0 || aSize == RSqlDatabase::EMaxCompaction, ESqlPanicBadArgument);
+	TInt pageSize = PageSizeL(aDbName);//PageSizeL() will disable/enable the authorizer
+	TInt pageCount = KMaxTInt;
+	if(aSize > 0)
+		{//64-bit calculations to avoid the overflow in case if (aSize + pageSize) >= KMaxTInt.
+		pageCount = (TInt64)((TInt64)aSize + pageSize - 1) / pageSize;
+		}
+	if(pageCount > 0)
+		{
+		iAuthorizerDisabled	= ETrue;
+		CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+		__SQLLEAVE_IF_ERROR(::DbCompact(iDbHandle, aDbName, pageCount, pageCount));
+		CleanupStack::PopAndDestroy();
+		}
+	return pageCount * pageSize;
+	}
+
+/**
+This structure is used in case if the InitAttachedDbL() execution fails and the 
+executed operations ("attach database", "init compact") have to be reverted calling
+FinalizeAttachedDb().
+
+@see CSqlSrvDatabase::InitAttachedDbL
+@see CSqlSrvDatabase::FinalizeAttachedDb
+@see CSqlSrvDatabase::AttachCleanup
+
+@internalComponent
+*/
+NONSHARABLE_STRUCT(TAttachCleanup)
+	{
+	inline TAttachCleanup(CSqlSrvDatabase& aSelf, const TDesC& aDbName) :
+		iSelf(aSelf),
+		iDbName(aDbName)
+		{
+		}
+	CSqlSrvDatabase& iSelf;
+	const TDesC& iDbName;
+	};
+
+/**
+Cleanup function. Calls FinalizeAttachedDb() if InitAttachedDbL() has failed.
+
+@param aCleanup A pointer to a TAttachCleanup object that contains the needed for the cleanup information.
+
+@see TAttachCleanup
+
+@internalComponent
+*/
+void CSqlSrvDatabase::AttachCleanup(void* aCleanup)
+	{
+	TAttachCleanup* cleanup = reinterpret_cast <TAttachCleanup*> (aCleanup);
+	__SQLASSERT(cleanup != NULL, ESqlPanicBadArgument);
+	if(cleanup)
+		{
+		(void)cleanup->iSelf.FinalizeAttachedDb(cleanup->iDbName);
+		}
+	}
+
+/**
+Forms and executes "ATTACH DATABASE" SQL statement.
+If the database is not read-only:
+ - Makes the attached database journal file persistent.
+ - Initializes the attached database compaction mode.
+ - The attached database will be reindexed if the default collation has been changed.
+
+@param aFileData Attached database file data
+@param aDbName Attached database name. It must be unique (per database connection).
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+                      
+@see InitCompactionL
+@see ProcessSettingsL
+*/
+void CSqlSrvDatabase::InitAttachedDbL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
+	{
+	TPtrC dbFileName = aFileData.FileName();
+	TBool readOnlyDbFile = aFileData.IsReadOnly();
+	
+	InstallAuthorizerL();
+	iAuthorizerDisabled	= ETrue;
+	CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+	sqlite3_stmt* stmtHandle = StmtPrepare16L(iDbHandle, KAttachDb);
+	TInt err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 1, dbFileName.Ptr(), dbFileName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
+	if(err == KErrNone)
+		{
+		err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 2, aDbName.Ptr(), aDbName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
+		if(err == KErrNone)
+			{
+			err = StmtExec(stmtHandle);
+			}
+		}
+	TInt err2 = ::FinalizeStmtHandle(stmtHandle);
+	CleanupStack::PopAndDestroy();//TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled)
+	if(err == KErrNone && err2 != KErrNone)
+		{//::FinalizeStmtHandle() has failed
+		err = err2;
+		}
+	__SQLLEAVE_IF_ERROR(err);
+	
+	TAttachCleanup attachCleanup(*this, aDbName);
+	CleanupStack::PushL(TCleanupItem(&CSqlSrvDatabase::AttachCleanup, &attachCleanup));
+	
+	SetConfigL(aFileData.ConfigParams(), EFalse, aDbName);
+	
+	if(!readOnlyDbFile)
+		{
+		iAuthorizerDisabled	= ETrue;
+		CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+		ProcessSettingsL(aFileData, aDbName);
+		CleanupStack::PopAndDestroy();//TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled)
+		}
+	
+	CleanupStack::Pop();//TCleanupItem(&CSqlSrvDatabase::AttachCleanup, &attachCleanup)
+	}
+
+/**
+Forms and executes "DETACH DATABASE" SQL statement.
+If the database was scheduled for background compacting, the related database entry will be removed from
+the vaccum db map.
+
+@param aDbName Attached database name. It must be unique (per database connection).
+
+@return KErrNone, Operation completed successfully;
+		KErrNoMemory, an out of memory condition has occurred.
+                      Note that the function may also return some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+*/
+TInt CSqlSrvDatabase::FinalizeAttachedDb(const TDesC& aDbName)
+	{
+	ReleaseCompactEntry(aDbName);
+	iAuthorizerDisabled	= ETrue;
+	sqlite3_stmt* stmtHandle = NULL;
+	TRAPD(err, stmtHandle = StmtPrepare16L(iDbHandle, KDetachDb));
+	if(err == KErrNone)
+		{
+		err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 1, aDbName.Ptr(), aDbName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
+		if(err == KErrNone)
+			{
+			err = StmtExec(stmtHandle);
+			}
+		}
+	TInt err2 = ::FinalizeStmtHandle(stmtHandle);
+	if(err == KErrNone && err2 != KErrNone)
+		{//::FinalizeStmtHandle() has failed
+		err = err2;
+		}
+	iAuthorizerDisabled	= EFalse;
+	return err;
+	}
+
+/**
+Updates the security policies map (CSqlServer::iSecurityMap).
+
+Inserts a new item in the security map, or if such item already exists there - its reference counter will
+be incremented.
+The method guarantees that either the security map will be updated, or the method leaves and the security
+policies map stays unchanged.
+
+@param aAttachedDb True if the currently processed database is an attached database, false if it is the main db.
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 The secure database name format must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 "[SID]" refers to SID of the application which creates the database.
+@param aMapKey Output parameter. UTF8 encoded, zero-terminated string. On function exit cannot be NULL. 
+               It will be set to point to the security policies map key. No memory is allocated for the key.
+@param aSecurityPolicy Output parameter. On function exit cannot be NULL. It will be set to point to the security policies.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see RSqlSecurityMap
+@see CSqlServer
+@see TSqlSrvFileData
+@see CSqlSecurityPolicy
+*/
+void CSqlSrvDatabase::UpdateSecurityMapL(TBool aAttachedDb, const TSqlSrvFileData& aFileData, 
+										 const TUint8*& aMapKey, const CSqlSecurityPolicy*& aSecurityPolicy)
+	{
+	//Check if a copy of the database security policies is already in the security map.
+	aMapKey = SecurityMapKeyL(aFileData.FileName());
+	TSqlSecurityPair* pair = ::SqlServer().SecurityMap().Entry(aMapKey);
+	if(pair)
+		{
+		//Yes, it is in the map. Increment the reference counter.
+		//(It will be decremented when detaching the database).
+		pair->iRefCounter.Increment();
+		aMapKey = pair->iKey;
+		aSecurityPolicy = pair->iData;
+		}
+	else
+		{
+		//No, it is not in the map. Read the security policies from the security policies tables and 
+		//insert a new item in the map.
+		__SQLASSERT(aMapKey != NULL, ESqlPanicInternalError);
+		aMapKey = ::CreateStrCopyLC(aMapKey);
+		CSqlSecurityPolicy* securityPolicy = aAttachedDb ? ::LoadAttachedDbSecurityPolicyLC(aFileData) :
+		                                                   ::LoadDbSecurityPolicyLC(iDbHandle);
+		__SQLLEAVE_IF_ERROR(::SqlServer().SecurityMap().Insert(aMapKey, securityPolicy));
+		CleanupStack::Pop(2);//iSecurityMap owns aMapKey and securityPolicy objects
+		aSecurityPolicy = securityPolicy;
+		}
+	__SQLASSERT(aMapKey != NULL, ESqlPanicInternalError);
+	__SQLASSERT(aSecurityPolicy != NULL, ESqlPanicInternalError);
+	}
+
+/**
+Removes attached secure database entries from the maps.
+
+The function will search the security policies map (CSqlServer::iSecurityMap) and the attached databases
+map (CSqlSrvDatabase::iAttachDbMap) for entries which correspond to the database with aDbName name,
+and will remove the entries.
+
+The sequence of the performed by the function operations is:
+1. Looks for a map item which key is aDbName in iAttachDbMap map.
+2. If such pair exists, the data part of the pair is used as a key in iSecurityMap map.
+3. Remove the iSecurityMap map item pointed by the data part of the found pair.
+4. Remove the iAttachDbMap map item pointed by aDbName.
+
+@param aDbName Attached database name. It must be unique (per database connection).
+
+@leave KErrGeneral It is not possible to convert aDbName parameter to UTF8 encoded string.
+
+@see CSqlSrvDatabase::DoAttachDbL()
+@see CSqlSrvDatabase::DoAttachSecureDbL()
+@see RSqlSecurityMap
+@see RSqlAttachDbMap
+@see CSqlServer
+@see CSqlSrvDatabase
+*/
+void CSqlSrvDatabase::RemoveFromMapsL(const TDesC& aDbName)
+	{
+	TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
+	if(!::UTF16ToUTF8Z(aDbName, ptr))
+		{
+		__SQLLEAVE(KErrGeneral);	
+		}
+	TSqlAttachDbPair* attachDbPair = iAttachDbMap.Entry(iFileNameBuf);
+	if(attachDbPair)
+		{//aDbName refers to attached secure database
+		::SqlServer().SecurityMap().Remove(attachDbPair->iData);
+		iAttachDbMap.Remove(iFileNameBuf);
+		}
+	}
+
+/**
+Inserts a new entry in the attached databases map (CSqlSrvDatabase::iAttachDbMap).
+
+The method guarantees that either a new [logical db name, secure db name] pair will be inserted in
+iAttachDbMap or the method fails and the content of iAttachDbMap remains unchanged.
+
+@param aDbFileName Database file name, including the path.
+@param aDbName Database name.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KErrGeneral, it is not possible to convert the function parameters to UTF8 encoded strings.
+
+@see RSqlAttachDbMap
+@see CSqlSrvDatabase
+*/
+void CSqlSrvDatabase::InsertInAttachDbMapL(const TDesC& aDbFileName, const TDesC& aDbName)
+	{
+	//Convert aDbName to UTF8, zero-terminated name
+	TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
+	if(!::UTF16ToUTF8Z(aDbName, ptr))
+		{
+		__SQLLEAVE(KErrGeneral);	
+		}
+	const TUint8* mapKey = ::CreateStrCopyLC(iFileNameBuf);
+	const TUint8* mapData = SecurityMapKeyL(aDbFileName);
+	mapData = ::CreateStrCopyLC(mapData);
+	__SQLLEAVE_IF_ERROR(iAttachDbMap.Insert(mapKey, mapData));
+	CleanupStack::Pop(2);//iAttachDbMap owns mapKey amd mapData.
+	}
+
+/**
+Processes the database settings that are currently stored in the settings table.
+Makes the journal file persistent.
+Initializes the database compaction mode.
+Based on the current settings the database may be configured to become 'up-to-date'.
+This configuration may include reindexing the database if the collation dll has
+changed and/or executing database configuration file operations.
+
+@param aFileData The file data object,
+@param aDbName Logical database name: "main" for the main database or attached database name,
+				        
+@leave The function may leave with system-wide error codes or SQL errors of ESqlDbError type
+
+@panic SqlDb 7 In _DEBUG mode if aFileData does not refer to a r/w database file.
+*/
+void CSqlSrvDatabase::ProcessSettingsL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
+	{
+	__SQLASSERT(!aFileData.IsReadOnly(), ESqlPanicInternalError);
+#if !defined(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)
+	//Make the journal file persistent - done by SQLite automatically because the locking mode is EXCLUSIVE
+	//__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KPersistentJournalPragma, KPersist, aDbName));
+	//Load the current settings
+	TFileName storedCollationDllName;
+	TInt storedDbConfigFileVer = -1;
+	TInt currVacuumMode = -1;
+	__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, aDbName, currVacuumMode));
+	//currVacuumMode == ESqliteVacuumOff ==> This is a database created not by the SQL server
+	TSqlCompactionMode compactionMode = currVacuumMode == ESqliteVacuumOff ? ESqlCompactionManual : ESqlCompactionNotSet;
+	TSqlDbSysSettings dbSettings(iDbHandle);
+	dbSettings.LoadSettingsL(aDbName, storedCollationDllName, storedDbConfigFileVer, compactionMode);
+	__SQLASSERT(currVacuumMode == ESqliteVacuumOff ? compactionMode == ESqlCompactionManual : 1, ESqlPanicInternalError);
+	if(aFileData.ContainHandles() && aFileData.IsCreated())
+		{
+		compactionMode = aFileData.ConfigParams().iCompactionMode;
+		if(compactionMode == ESqlCompactionNotSet)
+			{
+			compactionMode = KSqlDefaultCompactionMode;
+			}
+		//This is a just created private database. Store the compaction mode (the compaction mode may have been set using a config string).
+		StoreSettingsL(storedCollationDllName, storedDbConfigFileVer, compactionMode);
+		}
+	//Init the database compaction mode
+	InitCompactionL(compactionMode, aFileData.ConfigParams().iFreePageThresholdKb, aFileData.FileName(), 
+					(TSqliteVacuumMode)currVacuumMode, aDbName);
+	//Based on the current settings, apply any necessary configuration updates to the database
+	ApplyConfigUpdatesL(storedCollationDllName, storedDbConfigFileVer, aFileData, aDbName);	
+#endif // !(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)			
+	}
+		
+/**
+Applies any necessary configuration updates to the database, based on the current settings 
+in the settings table and how the database is being used (i.e. 'Opened' or 'Attached'). 
+The applied configuration may include:
+- Reindexing the main database and all attached databases, if the collation dll has been changed.
+After the reindexation the new collation dll name will be stored in the settings table of the database.
+- Executing all supported operations on the database that are specified in a database configuration 
+file, if such a file exists and has not already been processed. 
+The settings table will updated with the current version of the database configuration file if the file 
+is processed.
+
+@param aStoredCollationDllName The name of the collation dll that is stored in the settings table,
+@param aStoredDbConfigFileVersion The database configuration file version that is stored in the settings table,
+@param aFileData   The file data object,
+@param aDbName Logical database name: "main" for the main database or attached database name,
+
+@leave The function may leave with system-wide error codes or SQL errors of ESqlDbError type
+*/
+void CSqlSrvDatabase::ApplyConfigUpdatesL(const TDesC& aStoredCollationDllName, const TInt& aStoredDbConfigFileVersion, 
+										  const TSqlSrvFileData& aFileData, const TDesC& aDbName)
+	{
+	TSqlDbSysSettings dbSettings(iDbHandle);
+	//Check whether reindexing is necessary
+	if(::SqlServer().CollationDllName().CompareF(aStoredCollationDllName) != 0)
+		{
+		dbSettings.ReindexDatabaseL(aDbName, ::SqlServer().CollationDllName());
+		}
+
+	//Perform any necessary configuration file updates to the database.
+	//We do not want failures here to cause the database to fail
+	//to be opened and so any leave error is TRAPed and ignored
+	//(the error is logged in _DEBUG mode)
+	TRAPD(err, dbSettings.ConfigureDatabaseL(aStoredDbConfigFileVersion, aFileData, aDbName));
+	if(KErrNone != err)
+		{
+		__SQLLOG_ERR(_L("SQLLOG: CSqlSrvDatabase::ApplyConfigUpdatesL() - ConfigureDatabaseL() failed with error code %d"), err);	
+		}
+	}
+
+/**
+Sets the "cache size" and "page size" parameter values, if their values are valid.
+This is done formatting and executing PRAGMA statements.
+@param aConfigParams   This object contains the cofiguration parameters
+@param aSetPageSize If true, the page size will be set, otherwise not.
+                    The aSetPageSize is set to true if:
+                    1) The operation is "create database"
+                    2) The operation is "open private database"
+@param aLogicalDbName Parameter with default value of KNullDesC. If aLogicalDbName length is not 0, then the 
+                      "cache_size" pragma will be executed on the attached database with aLogicalDbName name. 
+*/
+void CSqlSrvDatabase::SetConfigL(const TSqlSrvConfigParams& aConfigParams, TBool aSetPageSize, const TDesC& aLogicalDbName)
+	{
+	__SQLASSERT(aConfigParams.iPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iPageSize >= 0, ESqlPanicBadArgument);
+	__SQLASSERT(aConfigParams.iCacheSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iCacheSize >= 0, ESqlPanicBadArgument);
+	if(aSetPageSize && aConfigParams.iPageSize != TSqlSrvConfigParams::KConfigPrmValueNotSet)
+		{
+		__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KPageSizePragma, aConfigParams.iPageSize));
+		}
+	
+	const TDesC& logicalDbName = aLogicalDbName.Length() > 0 ? aLogicalDbName : KMainDb16;
+	
+	//Setting the cache size.
+	//Step 1: Check if aConfigParams.iCacheSize value is set. If it is set, then use it.
+	if(aConfigParams.iCacheSize != TSqlSrvConfigParams::KConfigPrmValueNotSet)
+		{
+		__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KCacheSizePragma, aConfigParams.iCacheSize, logicalDbName));
+		}
+	else
+		{
+	//Step 2: aConfigParams.iCacheSize value is not set. Then check if aConfigParams.iSoftHeapLimitKb value is set.
+		if(aConfigParams.iSoftHeapLimitKb != TSqlSrvConfigParams::KConfigPrmValueNotSet)
+			{
+			__SQLASSERT(aConfigParams.iSoftHeapLimitKb >= TSqlSrvConfigParams::KMinSoftHeapLimitKb && 
+			            aConfigParams.iSoftHeapLimitKb <= TSqlSrvConfigParams::KMaxSoftHeapLimitKb, ESqlPanicInternalError);
+	//Step 3: aConfigParams.iSoftHeapLimitKb value is set. Then use it to calculate the cache size. But we need the page size first.
+    //        aLogicalDbName is used instead of logicalDbName because PageSizeL() if called with non-zero length name, 
+	//        "thinks" it is the main database name. KMainDb16 will be interpreted as an attached database name. 
+		TInt pageSize = PageSizeL(aLogicalDbName);
+	//Step 4: Calculate the cache size.
+			TInt cacheSize = ((TInt64)aConfigParams.iSoftHeapLimitKb * 1024) / pageSize;//"TInt64" cast is used because of a possible overflow
+	//Step 5: Set the cache size.
+			__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KCacheSizePragma, cacheSize, logicalDbName));
+			}
+		}
+	}
+
+/**
+Initializes the database compaction mode.
+If the aCompactionMode parameter is ESqlCompactionBackground, the database with aDbFileName file name will be added
+to the compactor for background compacting.
+
+@param aCompactionMode The database compaction mode. See TSqlCompactionMode enum for the supported database compaction modes.
+@param aFreePageThresholdKb Free page threshold. The background compaction won't start if the free pages size in Kb is less than
+						  the free page threshold.
+@param aDbFileName Database file name including full path
+@param aCurrentVacuumMode The current SQLite vacuum mode, one of TSqliteVacuumMode enum item values.
+						  If the current database vacuum mode is ESqliteVacuumOff, which means 
+						  the database has been created not by the SQL server, 
+						  then the "off" vacuum mode is kept unchanged.
+@param aDbName "main" or the attached database name
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                     Note that the function may also leave with some other database specific 
+                     errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see TSqlCompactionMode
+@see CSqlCompactor
+@see TSqliteVacuumMode
+
+@panic SqlDb 4 In _DEBUG mode if aCompactionMode parameter value is invalid.
+*/
+void CSqlSrvDatabase::InitCompactionL(TSqlCompactionMode aCompactionMode, TInt aFreePageThresholdKb, 
+									  const TDesC& aDbFileName, TSqliteVacuumMode aCurrentVacuumMode, const TDesC& aDbName)
+	{
+	__SQLASSERT(aCompactionMode == ESqlCompactionManual || aCompactionMode == ESqlCompactionBackground || aCompactionMode == ESqlCompactionAuto, ESqlPanicBadArgument);
+	__SQLASSERT(aCurrentVacuumMode == ESqliteVacuumOff || aCurrentVacuumMode == ESqliteVacuumAuto || 
+			    aCurrentVacuumMode == ESqliteVacuumIncremental, ESqlPanicBadArgument);
+	__SQLASSERT(aFreePageThresholdKb >= 0, ESqlPanicBadArgument);
+	TSqliteVacuumMode newSqliteVacuumMode = aCompactionMode == ESqlCompactionAuto ? ESqliteVacuumAuto : ESqliteVacuumIncremental;
+	if(aCurrentVacuumMode == ESqliteVacuumOff)
+		{
+		newSqliteVacuumMode = ESqliteVacuumOff;
+		}
+	if(aCurrentVacuumMode != newSqliteVacuumMode)	
+		{
+		__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KAutoVacuumPragma, newSqliteVacuumMode, aDbName));
+		}
+	if(aCompactionMode == ESqlCompactionBackground)
+		{
+		NewCompactEntryL(aFreePageThresholdKb, aDbFileName, aDbName);
+		}
+	}
+
+/**
+Adds the aDbFileName database to the compactor object for background compacting.
+
+@param aFreePageThresholdKb Free page threshold in Kb. The background compaction won't start if the total size of the free pages
+						  is less than the free page threshold.
+@param aDbFileName Database file name including full path
+@param aDbName "main" or the attached database name
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                     Note that the function may also leave with some other database specific 
+                     errors categorised as ESqlDbError, and other system-wide error codes.
+
+@see CSqlCompactor
+@see RSqlCompactDbMap 
+*/
+void CSqlSrvDatabase::NewCompactEntryL(TInt aFreePageThresholdKb, const TDesC& aDbFileName, const TDesC& aDbName)
+	{
+	TSqlCompactSettings settings;
+	settings.iFreePageThresholdKb = aFreePageThresholdKb;
+	::SqlServer().Compactor().AddEntryL(aDbFileName, settings);
+	TInt err = KErrNoMemory;
+	HBufC* key = aDbName.Alloc();
+	HBufC* data = aDbFileName.Alloc();
+	if(key && data)
+		{
+		err = iCompactDbMap.Insert(key, data);//returns the index of the new entry
+		}
+	if(err < 0) //If either "key" or "data" or both is NULL, then "err" is KErrNoMemory and the next "if" will be executed.
+		{
+		delete data;
+		delete key;
+		::SqlServer().Compactor().ReleaseEntry(aDbFileName);
+		}
+	__SQLLEAVE_IF_ERROR(err);
+	}
+
+/**
+Removes database (identified by its logical name) from the compactor.
+
+@param aDbName "main" or the attached database name
+
+@see CSqlCompactor
+@see RSqlCompactDbMap 
+*/
+void CSqlSrvDatabase::ReleaseCompactEntry(const TDesC& aDbName)
+	{
+	TSqlCompactDbMapIterator compactDbIt(iCompactDbMap);
+	TSqlCompactDbPair compactDbPair;
+	while(compactDbIt.Next(compactDbPair))
+		{
+		if(::CompareNoCase(*compactDbPair.iKey, aDbName) == 0)
+			{
+			::SqlServer().Compactor().ReleaseEntry(*compactDbPair.iData);
+			iCompactDbMap.Remove(compactDbPair.iKey);
+			break;
+			}
+		}
+	}
+
+/**
+Cleanup function.
+Used during the construction phase of the CSqlSrvDatabase instance when a new database is created.
+If the database creation succeeds, the "init compaction" operation succeeds but some other init operation fail,
+the just created database file has to be deleted. But before that the database has to be removed from the compactor,
+because the compactor creates independent database connection that has to be closed before the database deletion.
+
+The database will be removed from the compactor as a result of the call.
+
+@param aCleanup A pointer to the CSqlSrvDatabase object
+*/
+void CSqlSrvDatabase::CompactCleanup(void* aCleanup)
+	{
+	CSqlSrvDatabase* self = reinterpret_cast <CSqlSrvDatabase*> (aCleanup);
+	__SQLASSERT(self != NULL, ESqlPanicBadArgument);
+	if(self)
+		{
+		self->ReleaseCompactEntry(KMainDb16);
+		}
+	}
+
+/**
+Retrieves the database page size.
+If the request is for the main database page size and if the size is not retrieved yet, then the page size value will be 
+cached in iPageSize data member.
+
+@param aDbName Attached database name or KNullDesC for the main database
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                      Note that the function may also leave with some other database specific 
+                      errors categorised as ESqlDbError, and other system-wide error codes.
+
+@return The database page size 
+*/
+TInt CSqlSrvDatabase::PageSizeL(const TDesC& aDbName)
+	{
+	if(iPageSize > 0 && aDbName == KNullDesC)
+		{
+		return iPageSize;	
+		}
+	iAuthorizerDisabled	= ETrue;
+	CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
+	TInt pageSize = 0;
+	__SQLLEAVE_IF_ERROR(::DbPageSize(iDbHandle, aDbName, pageSize));
+	CleanupStack::PopAndDestroy();
+	__SQLASSERT(pageSize > 0, ESqlPanicInternalError);
+	if(aDbName == KNullDesC)
+		{
+		iPageSize = pageSize;	
+		}
+	return pageSize;
+	}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////        ConstructL() methods      ///////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Second phase construction method. Creates a new secure database file.
+If the function fails, the database file will be closed and deleted.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+@param aSecurityPolicy Database security policy
+
+@panic SqlDb 4 In _DEBUG mode if aSecurityPolicy is NULL.
+*/
+void CSqlSrvDatabase::ConstructCreateSecureL(const TSqlSrvFileData& aFileData, CSqlSecurityPolicy* aSecurityPolicy)
+	{
+	__SQLASSERT(aSecurityPolicy != NULL, ESqlPanicBadArgument);
+	//Insert a new item in the security policies map.
+	CleanupStack::PushL(aSecurityPolicy);
+	const TUint8* mapKey = SecurityMapKeyL(aFileData.FileName());
+	mapKey = ::CreateStrCopyLC(mapKey);
+	__SQLLEAVE_IF_ERROR(::SqlServer().SecurityMap().Insert(mapKey, aSecurityPolicy));
+	CleanupStack::Pop(2);//iSecurityMap owns mapKey and aSecurityPolicy.
+	iSecureDbName = mapKey;
+	iSecurityPolicy = aSecurityPolicy;
+	//
+	DoCommonConstructCreateL(aFileData, ETrue);
+	}
+
+/**
+Second phase construction method. Creates a new non-secure database file.
+If the function fails, the database file will be closed and deleted.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+*/
+void CSqlSrvDatabase::ConstructCreateL(const TSqlSrvFileData& aFileData)
+	{
+	DoCommonConstructCreateL(aFileData, EFalse);
+	}
+
+//Called by the two "Contruct&Create" methods: ConstructCreateL() and ConstructCreateSecureL().
+//The aSecureDb parameter tells which method is the caller.
+//The function performs common construction and initialization:
+// - creates the database file
+// - makes the journal file persistent
+// - initializes the database compaction mode
+// - stores the initial settings in the settings table, including the current collation dll name
+// - stores the security settings and installs the authorizer, if aSecureDb is true
+// - installs the user-defined functions
+// - installs collations
+//If the method fails and the error is not KErrAlreadyExists, the database file will be closed and deleted.
+void CSqlSrvDatabase::DoCommonConstructCreateL(const TSqlSrvFileData& aFileData, TBool aSecureDb)
+	{
+	__SQLASSERT(!iDbHandle, ESqlPanicInternalError);
+	__SQLASSERT(aSecureDb ? iSecurityPolicy != NULL : ETrue, ESqlPanicInternalError);
+	CreateNewDbFileL(aFileData);
+	TDbFileCleanup dbFileCleanup(aFileData, iDbHandle);
+	CleanupStack::PushL(TCleanupItem(&DbFileCleanup, &dbFileCleanup));
+	//Make the journal file persistent - done by SQLite automatically because the locking mode is EXCLUSIVE
+	//::ExecPragma(iDbHandle, iAuthorizerDisabled, KPersistentJournalPragma, KPersist);
+	//Init database compaction mode
+	TSqlCompactionMode compactionMode = aFileData.ConfigParams().iCompactionMode;
+	if(compactionMode == ESqlCompactionNotSet)
+		{
+		compactionMode = KSqlDefaultCompactionMode;
+		}
+	TInt currVacuumMode = -1;
+	__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, KNullDesC, currVacuumMode));
+	//currVacuumMode == ESqliteVacuumOff ==> This is a database created not by the SQL server
+	InitCompactionL(compactionMode, aFileData.ConfigParams().iFreePageThresholdKb, aFileData.FileName(), (TSqliteVacuumMode)currVacuumMode);
+	CleanupStack::PushL(TCleanupItem(&CSqlSrvDatabase::CompactCleanup, this));
+	//Store the initial settings in the settings table (including the current collation dll name)
+	StoreSettingsL(::SqlServer().CollationDllName(), KSqlNullDbConfigFileVersion, compactionMode);
+	if(aSecureDb)
+		{
+		//Store the security policies in the security policies tables.
+		TSqlDbSysSettings dbSysSettings(iDbHandle);
+		dbSysSettings.StoreSecurityPolicyL(*iSecurityPolicy);
+		}
+	InstallAuthorizerL();
+	InstallUDFsL();
+	InstallCollationsL();
+	CleanupStack::Pop(2);//CompactCleanup, DbFileCleanup
+	SQLPROFILER_DB_CREATE((TUint)iDbHandle, aFileData.FileName());
+	}
+
+/**
+Second phase construction method. Opens an existing  secure database file.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+*/
+void CSqlSrvDatabase::ConstructOpenSecureL(const TSqlSrvFileData& aFileData)
+	{
+	DoCommonConstructOpenL(aFileData, ETrue);
+	}
+
+/**
+Second phase construction method. Opens an existing  non-secure database file.
+
+@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
+     			 file session reference and some other database file related properties.
+				 If this is a secure database, then the format of the name must be:
+				 \<drive\>:\<[SID]database file name excluding the path\>.
+				 If this is a non-secure database, then the file name has to be the full database file name.
+				 "[SID]" refers to SID of the application which creates the database.
+				 If this is application's private database, then the format of aFileData is as it is described
+				 in TSqlSrvFileData::SetFromHandleL() comments.
+@see TSqlSrvFileData::SetFromHandleL()
+*/
+void CSqlSrvDatabase::ConstructOpenL(const TSqlSrvFileData& aFileData)
+	{
+	DoCommonConstructOpenL(aFileData, EFalse);
+	}
+
+//Opens a database and does all necessary initializations
+//Called by the two "Contruct&Open" methods: ConstructOpenL() and ConstructOpenSecureL().
+//The aSecureDb parameter tells which method is the caller.
+//The function performs common construction and initialization:
+// - opens the database file
+// - installs the user-defined functions
+// - installs collations
+// - installs the authoriser callback
+void CSqlSrvDatabase::DoCommonConstructOpenL(const TSqlSrvFileData& aFileData, TBool aSecureDb)
+	{
+	OpenExistingDbFileL(aFileData);//iDbHandle is valid after a successful call
+	//The user-defined collations must be installed before the possible database reindexing!!!
+	InstallCollationsL();
+	if(!aFileData.IsReadOnly())
+		{//No need to disable the authorizer since it is not installed yet.
+		 //Make sure that the user-defined collation have been installed before the reindexing operation.
+		ProcessSettingsL(aFileData, KMainDb16);
+		}
+	if(aSecureDb)
+		{
+		const TUint8* mapKey = NULL;
+		//Load database security policy, update the security policy map
+		UpdateSecurityMapL(EFalse, aFileData, mapKey, iSecurityPolicy);
+		mapKey = NULL;//it is not used
+		//Check that the caller has at least one of {Schema, Read, Write} policies.
+		BasicSecurityPolicyCheckL(*iSecurityPolicy);
+		}
+	//Install user-defined functions.
+	InstallUDFsL();
+	
+	//Install the authorizer.
+	InstallAuthorizerL();
+	
+    SQLPROFILER_DB_OPEN((TUint)iDbHandle, aFileData.FileName());
+	}
+
+/*
+Implementation of the like() SQL function.  This function implements
+the user defined LIKE operator.  The first argument to the function is the
+pattern and the second argument is the string.  So, the SQL statements:
+A LIKE B
+is implemented as like(B, A).
+
+@param aContext Function call context;
+@param aArgc Number of LIKE arguments: 2 for the standard LIKE operator, 3 for the LIKE operator with an ESCAPE clause;
+@param aArgv LIKE arguments;
+
+@internalComponent
+*/
+void CSqlSrvDatabase::LikeSqlFunc(sqlite3_context* aContext, int aArgc, sqlite3_value** aArgv)
+	{
+  	TUint escapeChar = 0;
+	if(aArgc == 3)
+		{
+    	//The escape character string must consist of a single UTF16 character.
+    	//Otherwise, return an error.
+		const TUint16* esc = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[2]));
+		if(!esc)
+			{
+      		sqlite3_result_error(aContext, KErrMsg1, -1);
+			return;
+			}
+		if(User::StringLength(esc) != 1)
+			{
+      		sqlite3_result_error(aContext, KErrMsg2, -1);
+          	return;
+			}
+		escapeChar = *esc;			
+    	}
+	const TUint16* pattern   = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[0]));
+	const TUint16* candidate = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[1]));
+  	if(pattern && candidate)
+		{
+		TInt wildChar = '_';
+		TInt wildSeqChar = '%';
+		TPtrC16 patternStr(pattern, (TUint)sqlite3_value_bytes16(aArgv[0]) / sizeof(TUint16));
+		TPtrC16 candidateStr(candidate, (TUint)sqlite3_value_bytes16(aArgv[1]) / sizeof(TUint16));
+		TInt res = candidateStr.MatchC(patternStr, wildChar, wildSeqChar, escapeChar, 0/*collation level*/);
+    	sqlite3_result_int(aContext, res >= 0);
+		//RDebug::Print(_L("--res=%d, pattern=%S, candidate=%S\r\n"), res, &patternStr, &candidateStr);
+		}
+	}
+