persistentstorage/sql/SRC/Server/SqlSrvDbSysSettings.cpp
changeset 0 08ec8eefde2f
child 11 211563e4b919
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Store/Load database system settings (database settings, security policies)
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <f32file.h>
       
    19 #include <f32file64.h>
       
    20 #include <utf.h>				//CnvUtfConverter
       
    21 #include <sqldb.h>				//RSqlSecurityPolicy enum items
       
    22 #include "SqlSrvDbSysSettings.h"
       
    23 #include "SqlUtil.h"			//Sql2OsErrCode()
       
    24 #include "sqlite3.h"			//SQLITE API
       
    25 #include "SqliteSymbian.h"		//sqlite3SymbianLastOsError()
       
    26 #include "SqlSecurityImpl.h"	//CSqlSecurityPolicy
       
    27 #include "SqlSrvStatementUtil.h"//Global SQL execution functions
       
    28 #include "SqlSrvCollation.h"	//TSqlCollate
       
    29 #include "SqlSrvStrings.h"		//System table names
       
    30 #include "SqlSrvUtil.h"			//Global functions
       
    31 #include "SqlSrvFileData.h"		//TSqlSrvFileData
       
    32 
       
    33 extern TBool IsStatementSupported(const TDesC& aStatementIn, const TDesC& aDbName, TDes& aStatementOut);
       
    34 
       
    35 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    36 /////////////////////////////        Local const data   ///////////////////////////////////////////////////////
       
    37 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    38 
       
    39 enum
       
    40 	{
       
    41 	ESqlSystemVersion1 = 1,	//Base version
       
    42 	ESqlSystemVersion2 = 2,	//New field into "Settings" table - "Reserved" (unused, set to 0)
       
    43 	ESqlSystemVersion3 = 3,	//New field into "Settings" table - "CollationDllName"
       
    44 				            //Existing field in "Settings" table - "Reserved" - now used to store processed version of db config file
       
    45 	ESqlSystemVersion4 = 4	//"CompactionMode" field added
       
    46 	};
       
    47 
       
    48 //Current version of the system settings - reflects changes in the system tables.
       
    49 const TInt KSqlSystemVersion = ESqlSystemVersion4;
       
    50 
       
    51 //The database names in all statements are quoted to avoid the "sql injection" threat.
       
    52 //(At the moment there is no way to pass an invalid database name for these statements, because the database has to be attached
       
    53 // first and a parameter binding is used there. So, the quoting is just for safety and against changes in the future)
       
    54 
       
    55 _LIT(KCreateSettingsSql,"CREATE TABLE \"%S\".symbian_settings(Id INTEGER,Reserved INTEGER,CollationDllName TEXT, CompactionMode INTEGER);\x0");
       
    56 _LIT(KDropSettingsSql, "DROP TABLE IF EXISTS \"%S\".symbian_settings;\x0");
       
    57 _LIT(KInsertSettingsSql, "INSERT INTO \"%S\".symbian_settings VALUES(%d, %d,'%S',%d);\x0");
       
    58 _LIT(KUpdateCollationSettingsSql, "UPDATE \"%S\".symbian_settings SET CollationDllName='%S';\x0");
       
    59 _LIT(KUpdateFileVersionSettingsSql, "UPDATE \"%S\".symbian_settings SET Reserved=%d;\x0");
       
    60 _LIT(KGetSettingsSql, "SELECT * FROM \"%S\".symbian_settings;\x0");
       
    61 _LIT(KGetIndexSql, "SELECT name FROM \"%S\".sqlite_master WHERE type = 'index' AND sql LIKE '%%%S%%'\x0");
       
    62 _LIT(KSettingsTableCheckSql, "SELECT name from \"%S\".sqlite_master WHERE type = 'table' AND name = 'symbian_settings';\x0");
       
    63 _LIT(KReindexSql, "REINDEX \"%S\";\x0");
       
    64 
       
    65 _LIT8(KCreateSecuritySql,"CREATE TABLE symbian_security(Id INTEGER PRIMARY KEY AUTOINCREMENT,ObjectType INTEGER,ObjectName TEXT,PolicyType INTEGER,PolicyData BLOB);\x0");
       
    66 _LIT8(KInsertSecuritySql, "INSERT INTO symbian_security(ObjectType,ObjectName,PolicyType,PolicyData) VALUES(:V1,:V2,:V3,:V4);\x0");
       
    67 _LIT8(KGetSecuritySql, "SELECT * FROM symbian_security;\x0");
       
    68 
       
    69 _LIT8(KBeginTransactionSql, "BEGIN;\x0");
       
    70 _LIT8(KCommitTransactionSql, "COMMIT;\x0");
       
    71 _LIT8(KRollbackTransactionSql, "ROLLBACK;\x0");
       
    72 
       
    73 
       
    74 
       
    75 //KInsertSecuritySql statement - parameter indices
       
    76 const TInt KObjTypePrmIdx = 1;
       
    77 const TInt KObjNamePrmIdx = 2;
       
    78 const TInt KObjPolicyTypePrmIdx = 3;
       
    79 const TInt KObjPolicyDataPrmIdx = 4;
       
    80 
       
    81 //Default security policy - object type code and policy type code
       
    82 const TInt KDefaultObjType = -2;
       
    83 const TInt KDefaultPolicyType = -1;
       
    84 
       
    85 //Database security policy - object type code
       
    86 const TInt KDbObjType = -1;
       
    87 
       
    88 //KGetSettingsSql sql statement - column indices
       
    89 const TInt KSysVersionColIdx = 0;
       
    90 const TInt KConfigFileVersionColIdx = 1;
       
    91 const TInt KCollationDllNameColIdx = 2;
       
    92 const TInt KCompactionModeColIdx = 3;
       
    93 
       
    94 //KGetSecuritySql sql statement - column indices
       
    95 const TInt KObjTypeColIdx = 1;
       
    96 const TInt KObjNameColIdx = 2;
       
    97 const TInt KObjPolicyTypeColIdx = 3;
       
    98 const TInt KObjPolicyDataColIdx = 4;
       
    99 
       
   100 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   101 /////////////////////////////        Local functions   ////////////////////////////////////////////////////////
       
   102 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   103 
       
   104 //Finalzes the statement handle (aHandle argument). Used in stack cleanup operations.
       
   105 //Panic SqlDb 4 In _DEBUG mode if aHandle argument is NULL.
       
   106 static void FinalizeStatementHandle(void* aHandle)
       
   107 	{
       
   108 	__SQLASSERT(aHandle != NULL, ESqlPanicBadArgument);
       
   109 	sqlite3_stmt* stmtHandle = static_cast <sqlite3_stmt*> (aHandle);
       
   110 	(void)sqlite3_finalize(stmtHandle);
       
   111 	}
       
   112 
       
   113 //Transaction rollback. Used in stack cleanup operations.
       
   114 //Panic SqlDb 4 In _DEBUG mode if aDbHandle argument is NULL.
       
   115 static void RollbackTransaction(void* aDbHandle)
       
   116 	{
       
   117 	__SQLASSERT(aDbHandle != NULL, ESqlPanicBadArgument);
       
   118 	(void)::DbExecStmt8(reinterpret_cast <sqlite3*> (aDbHandle), KRollbackTransactionSql);
       
   119 	}
       
   120 
       
   121 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   122 /////////////////////////////      TSqlDbSysSettings   ////////////////////////////////////////////////////////
       
   123 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   124 
       
   125 /**
       
   126 Initializes TSqlDbSysSettings data members with default values.
       
   127 
       
   128 @param aDbHandle Database handle. TSqlDbSysSettings does not own aDbHandle argument.
       
   129 
       
   130 @panic SqlDb 4 In _DEBUG mode if aDbHandle argument is NULL.
       
   131 */
       
   132 TSqlDbSysSettings::TSqlDbSysSettings(sqlite3* aDbHandle) :
       
   133 	iDbHandle(aDbHandle)
       
   134 	{
       
   135 	__SQLASSERT(iDbHandle != NULL, ESqlPanicBadArgument);
       
   136 	}
       
   137 
       
   138 /**
       
   139 Creates the database security policy table and stores the security policy in the table.
       
   140 
       
   141 @param aSecurityPolicy   Database security policies container, which data needs to be persisted.
       
   142 
       
   143 @leave KErrNoMemory, an out of memory condition has occurred.
       
   144                   Note that the function may also leave with some other database specific 
       
   145                   errors categorised as ESqlDbError, and other system-wide error codes.
       
   146 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   147 */
       
   148 void TSqlDbSysSettings::StoreSecurityPolicyL(const CSqlSecurityPolicy& aSecurityPolicyCon)
       
   149 	{
       
   150 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   151 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KBeginTransactionSql()));
       
   152 	CleanupStack::PushL(TCleanupItem(&RollbackTransaction, iDbHandle));
       
   153 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KCreateSecuritySql()));
       
   154 	StoreSecurityPoliciesL(aSecurityPolicyCon);
       
   155 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KCommitTransactionSql()));
       
   156 	CleanupStack::Pop();//TCleanupItem(&RollbackTransaction, iDbHandle)
       
   157 	}
       
   158 
       
   159 /**
       
   160 Stores the database system settings in the settings table. The settings table is recreated.
       
   161 
       
   162 @param aDbName Logical database name: "main" for the main database or attached database name,
       
   163 @param aCollationDllName Collation dll name. It uniquely identifies the current collation method in use.
       
   164                          If the default collation method changes later then the database will be reindexed 
       
   165                          and the new collation dll name will replace the existing one in the settings table.
       
   166 @param aDbConfigFileVersion Current config file version or KSqlNullDbConfigFileVersion
       
   167 @param aCompactionMode Database compaction mode, one of TSqlCompactionMode enum item values (except ESqlCompactionNotSet)
       
   168 
       
   169 @see TSqlCompactionMode
       
   170 
       
   171 @leave KErrNoMemory, an out of memory condition has occurred.
       
   172                   Note that the function may also leave with some other database specific 
       
   173                   errors categorised as ESqlDbError, and other system-wide error codes.
       
   174 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   175 @panic SqlDb 4 In _DEBUG mode if aCompactionMode parameter value is invalid.
       
   176 */
       
   177 void TSqlDbSysSettings::StoreSettingsL(const TDesC& aDbName, const TDesC& aCollationDllName, TInt aDbConfigFileVersion, TSqlCompactionMode aCompactionMode)
       
   178 	{
       
   179 	__SQLASSERT(aCompactionMode == ESqlCompactionManual || aCompactionMode == ESqlCompactionBackground || aCompactionMode == ESqlCompactionAuto, ESqlPanicBadArgument);
       
   180 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   181 	HBufC* buf = HBufC::NewLC(Max((TInt)sizeof(KDropSettingsSql), 
       
   182 							  Max((TInt)sizeof(KCreateSettingsSql), (TInt)sizeof(KInsertSettingsSql))) + 
       
   183 							  aDbName.Length() + aCollationDllName.Length() + 10);
       
   184 	TPtr sql = buf->Des();
       
   185 	//Begin transaction
       
   186 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KBeginTransactionSql()));
       
   187 	CleanupStack::PushL(TCleanupItem(&RollbackTransaction, iDbHandle));	
       
   188 	//Recreate the "settings" table and store the default collation there (the DLL name)
       
   189 	sql.Format(KDropSettingsSql(), &aDbName);
       
   190 	__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, sql));
       
   191 	sql.Format(KCreateSettingsSql, &aDbName);
       
   192 	__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, sql));
       
   193 	sql.Format(KInsertSettingsSql(), &aDbName, KSqlSystemVersion, aDbConfigFileVersion, &aCollationDllName, aCompactionMode);
       
   194 	__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, sql));
       
   195 	//Commit transaction
       
   196 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KCommitTransactionSql()));
       
   197 	CleanupStack::Pop();//TCleanupItem(&RollbackTransaction, iDbHandle)
       
   198 	CleanupStack::PopAndDestroy(buf);
       
   199 	}
       
   200 
       
   201 /**
       
   202 Read security policies from security policy table.
       
   203 
       
   204 The method does not guarantee that either the security policies will be read from the 
       
   205 security table and stored in aSecurityPolicy parameter or aSecurityPolicy argument 
       
   206 stays unchanged in a case of failure.
       
   207 
       
   208 @param aSecurityPolicyCon Security policies container which needs to be initializeed with 
       
   209 						  the database security policies.
       
   210 
       
   211 @leave KErrNoMemory, an out of memory condition has occurred;
       
   212 	   KErrGeneral, missing or invalid data in the system tables;
       
   213                   Note that the function may also leave with some other database specific 
       
   214                   errors categorised as ESqlDbError, and other system-wide error codes.
       
   215 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   216 */
       
   217 void TSqlDbSysSettings::LoadSecurityPolicyL(CSqlSecurityPolicy& aSecurityPolicyCon)
       
   218 	{
       
   219 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   220 	//Even if the version of the system settings is bigger than the current one (KSqlSystemVersion constant),
       
   221 	//I think that all future modifications of the system tables shall not affect the already existing
       
   222 	//fields. So it is correct to think that all information available in version 1 should be available 
       
   223 	//(and accessible) in all future versions of the system settings.
       
   224 	//Note: no attempt shall be made here to modify the system tables structure! There may be more than one 
       
   225 	//      connection to the database being processed!
       
   226 	//
       
   227 	//Prepare statement handle
       
   228 	sqlite3_stmt* stmtHandle = ::StmtPrepare8L(iDbHandle, KGetSecuritySql());
       
   229 	CleanupStack::PushL(TCleanupItem(&FinalizeStatementHandle, stmtHandle));
       
   230 	//Read the security policies
       
   231 	TBool defaultPolicySet = EFalse;
       
   232 	TInt dbPolicySetFlag = 0;
       
   233 	TInt err;
       
   234 	while((err = ::StmtNext(stmtHandle)) == KSqlAtRow)
       
   235 		{
       
   236 		TInt objType = KDefaultObjType - 1;
       
   237 		TPtrC objName(KNullDesC);
       
   238 		TInt policyType = RSqlSecurityPolicy::ESchemaPolicy - 1;
       
   239 		TSecurityPolicy policy = ReadCurrSecurityPolicyL(stmtHandle, objType, objName, policyType);
       
   240 		switch(objType)
       
   241 			{
       
   242 			case KDefaultObjType:
       
   243 				if(defaultPolicySet)
       
   244 					{
       
   245 					__SQLLEAVE(KErrGeneral);//two "default policy" records in the table
       
   246 					}
       
   247 				StoreDefaultSecurityPolicyL(aSecurityPolicyCon, policy, dbPolicySetFlag);
       
   248 				defaultPolicySet = ETrue;
       
   249 				break;
       
   250 			case KDbObjType:
       
   251 				StoreDbSecurityPolicyL(aSecurityPolicyCon, policyType, policy, dbPolicySetFlag);
       
   252 				break;
       
   253 			case RSqlSecurityPolicy::ETable:
       
   254 				StoreDbObjSecurityPolicyL(aSecurityPolicyCon, objType, objName, policyType, policy);
       
   255 				break;
       
   256 			default:
       
   257 				__SQLLEAVE(KErrGeneral);
       
   258 				break;
       
   259 			}//end of "switch(aObjType)"
       
   260 		}
       
   261 	CleanupStack::PopAndDestroy();//cleanupItem (statement handle)
       
   262 	__SQLLEAVE_IF_ERROR(err);
       
   263 	if(!defaultPolicySet)
       
   264 		{
       
   265 		__SQLLEAVE(KErrGeneral);//no default policy
       
   266 		}
       
   267 	}
       
   268 	
       
   269 /**
       
   270 Loads the database system settings from the settings table.
       
   271 If the settings table does not exist then it is created with the default settings
       
   272 (the stored collation dll name will be empty and the stored database configuration 
       
   273 file version will be 0).
       
   274 
       
   275 @param aDbName Logical database name: "main" for the main database or attached database name,
       
   276 @param aCollationDllName Output parameter, will contain the stored collation dll name,
       
   277 @param aDbConfigFileVersion Output parameter, will contain the stored database config file version.
       
   278 @param aCompactionMode Output parameter. Database compaction mode (one of TSqlCompactionMode enum item values except ESqlCompactionNotSet).
       
   279 					   Note that the input value of this parameter might be ESqlCompactionManual if the this is a legacy database,
       
   280 					   created not by the SQL server.
       
   281 
       
   282 @see TSqlCompactionMode
       
   283 
       
   284 @leave KErrNoMemory, an out of memory condition has occurred.
       
   285        Note that the function may also leave with some other database specific 
       
   286        errors categorised as ESqlDbError, and other system-wide error codes..
       
   287 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   288 @panic SqlDb 7 In _DEBUG mode if the stored compaction mode is invalid.
       
   289 */	
       
   290 void TSqlDbSysSettings::LoadSettingsL(const TDesC& aDbName, TDes& aCollationDllName, TInt& aDbConfigFileVersion, TSqlCompactionMode& aCompactionMode)
       
   291 	{
       
   292 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   293 
       
   294 	aCollationDllName.Zero();
       
   295 	aDbConfigFileVersion = KSqlNullDbConfigFileVersion;	
       
   296 	if(aCompactionMode == ESqlCompactionNotSet)
       
   297 		{
       
   298 		aCompactionMode = KSqlDefaultCompactionMode;
       
   299 		}
       
   300 		
       
   301 	//If the system settings table does not exist then create it now.
       
   302 	//For a database created by the SQL Server this will only occur 
       
   303 	//when the database is being created in an application's private data cage -
       
   304 	//as part of this create call it is now being opened by the server.
       
   305 	//An externally created database is likely to not contain the settings table 
       
   306 	//and adding it here makes the database 'SQL Server-compatible'
       
   307 	if(!SettingsTableExistsL(aDbName))
       
   308 		{
       
   309 		StoreSettingsL(aDbName, aCollationDllName, KSqlNullDbConfigFileVersion, aCompactionMode); // store empty collation dll name, then reindexing will occur
       
   310 		}
       
   311 	else
       
   312 		{
       
   313 		//Get the settings from the existing table
       
   314 		TInt settingsVersion = 0;
       
   315 		GetSettingsL(aDbName, aCollationDllName, aDbConfigFileVersion, settingsVersion, aCompactionMode);
       
   316 		if(settingsVersion < KSqlSystemVersion)
       
   317 			{
       
   318 			//Recreate the settings table using the last version number format (this is what the old code did during reindexing)
       
   319 			StoreSettingsL(aDbName, aCollationDllName, aDbConfigFileVersion, aCompactionMode); // store empty collation dll name, then reindexing will occur
       
   320 			}
       
   321 		}
       
   322 	__SQLASSERT(aCompactionMode == ESqlCompactionManual || aCompactionMode == ESqlCompactionBackground || aCompactionMode == ESqlCompactionAuto, ESqlPanicInternalError);
       
   323 	}
       
   324 	
       
   325 /**
       
   326 Retrieves the database system settings from the settings table.
       
   327 
       
   328 @param aDbName Logical database name: "main" for the main database or attached database name,
       
   329 @param aCollationDllName Output parameter, will contain the stored collation dll name,
       
   330 @param aDbConfigFileVersion Output parameter, will contain the stored database config file version,
       
   331 @param aSettingsVersion Output parameter, will contain the version of the settings table.
       
   332 @param aCompactionMode Output parameter. Database compaction mode (one of TSqlCompactionMode enum item values except ESqlCompactionNotSet).
       
   333 
       
   334 @see TSqlCompactionMode
       
   335 
       
   336 @leave KErrGeneral, either unable to retrieve the data from the settings table or the 
       
   337 					stored table version or config file version is invalid or the stored compaction mode is invalid.
       
   338 	   KErrOverflow, aCollationDllName is not large enough to store the name of the 
       
   339 	   				 collation dll that is stored in the settings table.
       
   340 	   Note that the function may also leave with other system-wide error codes or SQL
       
   341 	   errors of ESqlDbError type
       
   342 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   343 */
       
   344 void TSqlDbSysSettings::GetSettingsL(const TDesC& aDbName, TDes& aCollationDllName, TInt& aDbConfigFileVersion, 
       
   345 									 TInt& aSettingsVersion, TSqlCompactionMode& aCompactionMode)
       
   346 	{
       
   347 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   348 
       
   349 	HBufC* buf = HBufC::NewLC(sizeof(KGetSettingsSql) + aDbName.Length());
       
   350 	TPtr sql = buf->Des();
       
   351 			
       
   352 	//Prepare statement handle
       
   353 	sql.Format(KGetSettingsSql(), &aDbName);
       
   354 	sqlite3_stmt* stmtHandle = ::StmtPrepare16L(iDbHandle, sql);
       
   355 	CleanupStack::PushL(TCleanupItem(&FinalizeStatementHandle, stmtHandle));
       
   356 	//Move to the first record
       
   357 	TInt err = ::StmtNext(stmtHandle);
       
   358 	__SQLLEAVE_IF_ERROR(err);
       
   359 	//Check that it is a valid row
       
   360 	if(err != KSqlAtRow)
       
   361 		{
       
   362 		__SQLLEAVE(KErrGeneral);
       
   363 		}
       
   364 	//Get the system settings version 
       
   365 	aSettingsVersion = sqlite3_column_int(stmtHandle, KSysVersionColIdx);
       
   366 	if(aSettingsVersion < ESqlSystemVersion1)
       
   367 		{
       
   368 		__SQLLEAVE(KErrGeneral);
       
   369 		}
       
   370 	if(aSettingsVersion > ESqlSystemVersion2)
       
   371 		{
       
   372 		//The "ConfigFileVersion" column exists and is used to store the most recent
       
   373 		//version of the database's config file (if there is one) that has 
       
   374 		//been successfully processed
       
   375 		aDbConfigFileVersion = sqlite3_column_int(stmtHandle, KConfigFileVersionColIdx);
       
   376 		if(aDbConfigFileVersion < KSqlNullDbConfigFileVersion)
       
   377 			{
       
   378 			__SQLLEAVE(KErrGeneral);
       
   379 			}
       
   380 			
       
   381 		//The "CollationDllName" column exists and its value can be read
       
   382 		const void* ptr = sqlite3_column_text16(stmtHandle, KCollationDllNameColIdx);
       
   383 		if(ptr)
       
   384 			{
       
   385 			TPtrC16 src(reinterpret_cast <const TUint16*> (ptr));
       
   386 			if(src.Length() > aCollationDllName.MaxLength())
       
   387 				{
       
   388 				__SQLLEAVE(KErrOverflow);	
       
   389 				}
       
   390 			aCollationDllName.Copy(src);
       
   391 			}
       
   392 		else
       
   393 	   		{
       
   394 	   		__SQLLEAVE(KErrGeneral);	
       
   395 	   		}
       
   396 		}
       
   397 	if(aSettingsVersion > ESqlSystemVersion3)
       
   398 		{
       
   399 		aCompactionMode = static_cast <TSqlCompactionMode> (sqlite3_column_int(stmtHandle, KCompactionModeColIdx));
       
   400 		if(aCompactionMode != ESqlCompactionManual && aCompactionMode != ESqlCompactionBackground && aCompactionMode != ESqlCompactionAuto)
       
   401 			{
       
   402 			__SQLLEAVE(KErrGeneral);
       
   403 			}
       
   404 		}
       
   405 	CleanupStack::PopAndDestroy();//TCleanupItem(&FinalizeStatementHandle, stmtHandle)	
       
   406 	CleanupStack::PopAndDestroy(buf);
       
   407 	}
       
   408 	
       
   409 /**
       
   410 Deletes and recreates all database indexes which use user-defined collation methods, from scratch.
       
   411 Also updates the database settings table with the name of the current collation dll.
       
   412 This is all performed as a single atomic transaction.
       
   413 
       
   414 @param aDbName Logical database name: "main" for the main database or attached database name,
       
   415 @param aCurrentCollationDllName The name of the current collation dll.
       
   416 
       
   417 @leave The function may leave with system-wide error codes or SQL errors of ESqlDbError type
       
   418 
       
   419 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   420 */
       
   421 void TSqlDbSysSettings::ReindexDatabaseL(const TDesC& aDbName, const TDesC& aCurrentCollationDllName)
       
   422 	{	
       
   423 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   424 
       
   425 	//Allocate memory for the SQL statements
       
   426 	HBufC* buf = HBufC::NewLC(Max((TInt)sizeof(KUpdateCollationSettingsSql), (TInt)sizeof(KReindexSql)) + 
       
   427 							  aDbName.Length() + aCurrentCollationDllName.Length());
       
   428 	TPtr sql = buf->Des();
       
   429 	
       
   430 	//Begin transaction
       
   431 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KBeginTransactionSql()));
       
   432 	CleanupStack::PushL(TCleanupItem(&RollbackTransaction, iDbHandle));	
       
   433 	
       
   434 	const TSqlCollationUtil collationUtil(iDbHandle);
       
   435 	//Issue a "REINDEX" command for each collation that has at least one index using it
       
   436 	for(TInt i = collationUtil.CollationCount()-1; i >= 0 ;--i)
       
   437 		{
       
   438 		TPtrC collationName = collationUtil.CollationName(i);
       
   439 		if(IndexExistsL(aDbName, collationName))
       
   440 			{
       
   441 			sql.Format(KReindexSql(), &collationName);
       
   442 			__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, sql));
       
   443 			}
       
   444 		}
       
   445 		
       
   446 	//Update the settings table to store the current collation DLL name
       
   447 	sql.Format(KUpdateCollationSettingsSql(), &aDbName, &aCurrentCollationDllName);
       
   448 	__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, sql));
       
   449 
       
   450 	//Commit transaction
       
   451 	__SQLLEAVE_IF_ERROR(::DbExecStmt8(iDbHandle, KCommitTransactionSql()));
       
   452 	CleanupStack::Pop(); //TCleanupItem(&RollbackTransaction, iDbHandle)
       
   453 	CleanupStack::PopAndDestroy(buf);
       
   454 	}
       
   455 
       
   456 /**
       
   457 Performs any necessary configuration file updates to the database if a 
       
   458 configuration file exists for the database that has not yet been processed.
       
   459 If a configuration file is processed then the database settings table will 
       
   460 be updated with the version of the configuration file that was processed.
       
   461 
       
   462 @param aStoredDbConfigFileVersion The configuration file version that is
       
   463 								  currently stored in the settings table
       
   464 @param aFileData The database file data
       
   465 
       
   466 @param aDbName Logical database name: "main" for the main database or attached database name
       
   467 
       
   468 @leave One of the system-wide error codes or SQL errors of ESqlDbError type
       
   469 
       
   470 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object)
       
   471 */
       
   472 void TSqlDbSysSettings::ConfigureDatabaseL(TInt aStoredDbConfigFileVersion, const TSqlSrvFileData& aFileData, 
       
   473 										   const TDesC& aDbName)
       
   474 	{	
       
   475 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   476 
       
   477 	if(!aFileData.IsSecureFileNameFmt())
       
   478 		{
       
   479 		//As a first implementation, config files will only be supported for 
       
   480 		//shared, secure databases - not for private, secure databases or public databases
       
   481 		return;	
       
   482 		}
       
   483 		
       
   484 	//Determine whether there is a configuration file 
       
   485 	//for this database that has not yet been processed
       
   486 	const CDbConfigFiles* dbConfigFiles = aFileData.DbConfigFiles();
       
   487 	if(dbConfigFiles)
       
   488 		{
       
   489 		//Get the database file name and extension to search for a corresponding config file
       
   490 		TPtrC dbName = aFileData.FileName();
       
   491 		TParse parse;
       
   492 		__SQLLEAVE_IF_ERROR(parse.Set(dbName, NULL, NULL));
       
   493 		TPtrC dbFileNameAndExt = parse.NameAndExt();
       
   494 		HBufC* matchingConfigFile = dbConfigFiles->FindConfigFile(dbFileNameAndExt);
       
   495 		if(matchingConfigFile)
       
   496 			{
       
   497 			//There exists a config file for this database - now check whether its
       
   498 			//version is greater than the version stored in the settings table and 
       
   499 			//only process the file if it is
       
   500 			TFileName configFileName;
       
   501 			configFileName.Copy(matchingConfigFile->Des());
       
   502 			TInt offset = configFileName.LocateReverse('.') ;
       
   503 			if(KErrNotFound != offset)
       
   504 				{
       
   505 				TInt lengthOfExt = configFileName.Length() - offset - 1;
       
   506 				TPtrC versionNum = configFileName.Right(lengthOfExt);				
       
   507 				TLex lex(versionNum);
       
   508 				TInt fileVersion = 0;
       
   509 				if(KErrNone == lex.Val(fileVersion))
       
   510 					{
       
   511 					if(fileVersion > aStoredDbConfigFileVersion)
       
   512 						{
       
   513 						//The latest version of the configuration file has not yet been processed, so do it now
       
   514 						__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ConfigureDatabaseL() - Processing config file %S"), configFileName);	
       
   515 						ExecuteConfigurationUpdateL(aFileData, configFileName, fileVersion, aDbName);
       
   516 						__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ConfigureDatabaseL() - SUCCESS! Config file %S was processed"), configFileName);	
       
   517 						}
       
   518 					else
       
   519 						{
       
   520 						__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ConfigureDatabaseL() - Not processing config file %S as this or a later version has already been processed"), configFileName);	
       
   521 						}
       
   522 					}
       
   523 				else
       
   524 					{
       
   525 					//Invalid config file name extension - it cannot be converted to an integer
       
   526 					__SQLLEAVE(KErrCorrupt);
       
   527 					}
       
   528 				}
       
   529 			else
       
   530 				{
       
   531 				//Invalid config file name - it doesn't contain the character '.'
       
   532 				__SQLLEAVE(KErrCorrupt);
       
   533 				}
       
   534 			}
       
   535 		else
       
   536 			{
       
   537 			__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ConfigureDatabaseL() - No config file found for database %S"), dbFileNameAndExt);	
       
   538 			}
       
   539 		}		
       
   540 	}
       
   541 	
       
   542 /**
       
   543 Executes the supported operations specified in the given database 
       
   544 configuration file and updates the settings table to store the 
       
   545 version of this configuration file.
       
   546 
       
   547 @param aFileData The database file data
       
   548 @param aMatchingConfigFile The configuration file that is to be processed
       
   549 @param aDbConfigFileVersion The configuration file version
       
   550 @param aDbName Logical database name: "main" for the main database or attached database name
       
   551 
       
   552 @leave KErrNoMemory, if an out of memory condition occurs.
       
   553        One of the other system-wide error codes if the configuration
       
   554        file fails to be opened or read.
       
   555        One of the SQL errors of ESqlDbError type if the update to the
       
   556        database settings table fails
       
   557 
       
   558 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   559 */
       
   560 void TSqlDbSysSettings::ExecuteConfigurationUpdateL(const TSqlSrvFileData& aFileData, 
       
   561 													const TDesC& aMatchingConfigFile,
       
   562 													TInt aDbConfigFileVersion,
       
   563 													const TDesC& aDbName)
       
   564 	{
       
   565 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   566 														
       
   567 	//Execute the specified database config file operations that are supported
       
   568 #ifdef SYSLIBS_TEST
       
   569 	TDriveUnit drive = EDriveC;
       
   570 #else
       
   571 	TDriveUnit drive = EDriveZ;
       
   572 #endif			
       
   573 	TFileName configFilePath;
       
   574 	TDriveName drvName = drive.Name();
       
   575 	configFilePath.Append(drvName);
       
   576 	configFilePath.Append(aFileData.PrivatePath());
       
   577 	configFilePath.Append(aMatchingConfigFile);
       
   578 	//If this method leaves then either the config file could not be 
       
   579 	//opened or read or an out of memory condition occured. Either way
       
   580 	//another attempt will be made to process the config file when the
       
   581 	//database is next opened
       
   582 	DoExecuteDbConfigFileOpsL(aFileData.Fs(), configFilePath, aDbName);
       
   583 												
       
   584 	//Now update the settings table to store the current version of the database config file.
       
   585 	//If this fails then another attempt will be made to process the config file and update
       
   586 	//the settings table when the database is next opened
       
   587 	TBuf<sizeof(KUpdateFileVersionSettingsSql) + KMaxFileName + 10> buf;
       
   588 	buf.Format(KUpdateFileVersionSettingsSql(), &aDbName, aDbConfigFileVersion);
       
   589 	__SQLLEAVE_IF_ERROR(::DbExecStmt16(iDbHandle, buf));
       
   590 	}
       
   591 
       
   592 /**
       
   593 Opens the specified database configuration file and executes those operations that 
       
   594 are specified in it which are currently supported (currently only 'CREATE INDEX' 
       
   595 operations are supported and will be executed).
       
   596 
       
   597 @param aFs The server's file server session
       
   598 @param aConfigFilePath The configuration file path
       
   599 @param aDbName Logical database name: "main" for the main database or attached database name
       
   600 
       
   601 @leave KErrNoMemory, if an out of memory condition occurs.
       
   602        One of the other system-wide error codes if the configuration
       
   603        file fails to be opened or read
       
   604 
       
   605 @panic SqlDb 2 In _DEBUG mode if iDbHandle is NULL (uninitialized TSqlDbSysSettings object).
       
   606 */
       
   607 void TSqlDbSysSettings::DoExecuteDbConfigFileOpsL(RFs& aFs, const TDesC& aConfigFilePath, const TDesC& aDbName)
       
   608 	{
       
   609 	__SQLASSERT(iDbHandle != NULL, ESqlPanicInvalidObj);
       
   610 	
       
   611 	//Open the config file and read it into a buffer
       
   612 	RFile64 file;
       
   613 	__SQLLEAVE_IF_ERROR(file.Open(aFs, aConfigFilePath, EFileRead)); 
       
   614 	CleanupClosePushL(file);
       
   615 	TInt64 size = 0;
       
   616 	__SQLLEAVE_IF_ERROR(file.Size(size));
       
   617 	if(size == 0)
       
   618 		{
       
   619 		//Config file is empty so just return
       
   620 		__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::DoExecuteDbConfigFileOpsL() - Config file %S is empty"), aConfigFilePath);	
       
   621 		CleanupStack::PopAndDestroy(); // file
       
   622 		return;
       
   623 		}
       
   624 	HBufC8* buffer = HBufC8::NewLC(size);
       
   625 	TPtr8 bufPtr = buffer->Des();
       
   626 	__SQLLEAVE_IF_ERROR(file.Read(bufPtr));
       
   627 
       
   628 	//Convert buffer to Unicode for processing (the configuration file is expected to be ASCII or UTF-8)
       
   629 	HBufC16* buf16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L(bufPtr);
       
   630 	CleanupStack::PushL(buf16);			
       
   631 	TPtrC16 ptr16 = buf16->Des();
       
   632 	
       
   633 	//Skip the BOM (byte ordering mark) at the start if there is one
       
   634 	if((ptr16.Locate(TChar(0xFEFF)) == 0) || (ptr16.Locate(TChar(0xFFFE)) == 0))
       
   635 		{
       
   636 		ptr16.Set(ptr16.Mid(1));	
       
   637 		}
       
   638 	 
       
   639 	//Parse the file contents and execute the specified
       
   640 	//config statements that are supported
       
   641 	ParseFileL(ptr16, aDbName);
       
   642 
       
   643 	CleanupStack::PopAndDestroy(3); // buf16, buffer, file
       
   644 	}
       
   645 	
       
   646 /**
       
   647 Parses the configuration file buffer, reading each SQL statement
       
   648 and processing it.
       
   649 
       
   650 @param aBuffer Buffer containing the configuration file contents
       
   651 @param aDbName Logical database name: "main" for the main database or attached database name
       
   652 
       
   653 @leave KErrNoMemory, if an out of memory condition occurs
       
   654 */
       
   655 void TSqlDbSysSettings::ParseFileL(const TDesC& aBuffer, const TDesC& aDbName)
       
   656 	{
       
   657 	TLex fileParser(aBuffer);
       
   658 	//While not end of file
       
   659 	while (!fileParser.Eos())
       
   660 		{
       
   661 		//Get the next of the SQL statements, which are seperated by semicolons
       
   662 		fileParser.SkipSpaceAndMark(); // skip any preceding whitespace before the next statement
       
   663 		while ((!fileParser.Eos()) && (fileParser.Peek() != ';'))
       
   664 			{
       
   665 			fileParser.Inc(); // continue to next character
       
   666 			}
       
   667 		TPtrC stmt = fileParser.MarkedToken(); // extract the marked token
       
   668 		fileParser.Inc();  // to skip the terminating ';' for next iteration
       
   669 	
       
   670 		//Process this statement
       
   671 		ProcessStatementL(stmt, aDbName);
       
   672 		}
       
   673 	}
       
   674 
       
   675 /**
       
   676 Process an SQL statement contained in the configuration file
       
   677 and executes it if it is a supported statement.
       
   678 Currently only 'CREATE INDEX' statements are supported.
       
   679 The statement can contain comments that are understood by SQLite
       
   680 - these can be in the form of an SQL comment or a 'C' comment, 
       
   681 as defined at http://www.sqlite.org/lang_comment.html.
       
   682 
       
   683 @param aStmt An SQL statement string, stripped of any whitespace 
       
   684 			 at the beginning of it
       
   685 @param aDbName Logical database name: "main" for the main database or attached database name
       
   686 
       
   687 @leave KErrNoMemory, if an out of memory condition occurs
       
   688 */
       
   689 void TSqlDbSysSettings::ProcessStatementL(const TDesC& aStmt, const TDesC& aDbName)
       
   690 	{	
       
   691 	__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Processing statement '%S'"), aStmt);	
       
   692 	
       
   693 	//If the statement only contained whitespace then just return
       
   694 	if(aStmt.Length() == 0)
       
   695 		{
       
   696 		__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Statement '%S' only contains whitespace - statement will be ignored"), aStmt);	
       
   697 		return;	
       
   698 		}
       
   699 		
       
   700 	//Check that the statement does not contain an unsupported comment style
       
   701 	if(KErrNotFound != aStmt.Find(_L("//")))
       
   702 		{
       
   703 		//The statement contains '//' which is an unsupported comment style, but rather
       
   704 		//than leave here and cause the full file to fail, we just ignore this statement
       
   705 		__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Statement '%S' contains invalid comment style - statement will be ignored"), aStmt);	
       
   706 		return;
       
   707 		}
       
   708 		
       
   709 	HBufC* stmtBuf = HBufC::NewLC(aStmt.Length() + 1 + aDbName.Length() + 1);
       
   710 	TPtr stmtPtr = stmtBuf->Des();
       
   711 	//If the 'aStmt' string is an SQL statement that is supported then execute it
       
   712 	if(::IsStatementSupported(aStmt, aDbName, stmtPtr))
       
   713 		{
       
   714 		TInt err = ::DbExecStmt16(iDbHandle, stmtPtr);
       
   715 		if(KErrNone == err)
       
   716 			{
       
   717 			__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Successfully executed statement '%S'"), aStmt);		
       
   718 			}
       
   719 		else
       
   720 			{
       
   721 			__SQLLOG_ERR(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Failed to execute the statement, err=%d"), err);		
       
   722 			if(err == KErrNoMemory)
       
   723 				{
       
   724 				__SQLLEAVE(err);	
       
   725 				}
       
   726 			}
       
   727 		}
       
   728 	else
       
   729 		{
       
   730 		__SQLLOG_STRING(_L("SQLLOG: TSqlDbSysSettings::ProcessStatementL() - Non-supported statement, will be ignored - '%S'"), aStmt);		
       
   731 		}
       
   732 	CleanupStack::PopAndDestroy(); // stmtBuf
       
   733 	}
       
   734 
       
   735 
       
   736 /**
       
   737 Stores the security policies into the security policies table.
       
   738 
       
   739 @param aSecurityPolicyCon Security policies container, which data needs to be persisted.
       
   740 
       
   741 @leave KErrNoMemory, an out of memory condition has occurred;
       
   742 	   KErrArgument, system table name found in the list of the tables, which need special protection;
       
   743                   	 Note that the function may also leave with some other database specific 
       
   744                   	 errors categorised as ESqlDbError, and other system-wide error codes.
       
   745 
       
   746 @panic SqlDb 4 In _DEBUG mode if aSecurityPolicy argument is NULL.
       
   747 */
       
   748 void TSqlDbSysSettings::StoreSecurityPoliciesL(const CSqlSecurityPolicy& aSecurityPolicyCon)
       
   749 	{
       
   750 	//Prepare the INSERT sql statement
       
   751 	sqlite3_stmt* stmtHandle = ::StmtPrepare8L(iDbHandle, KInsertSecuritySql());
       
   752 	CleanupStack::PushL(TCleanupItem(&FinalizeStatementHandle, stmtHandle));
       
   753 	//Store default security policy into the table
       
   754 	StoreSecurityPolicyL(stmtHandle, KDefaultObjType, KNullDesC, KDefaultPolicyType, aSecurityPolicyCon.DefaultPolicy());
       
   755 	//Store database security policies into the table
       
   756 	StoreSecurityPolicyL(stmtHandle, KDbObjType, KNullDesC, RSqlSecurityPolicy::ESchemaPolicy, aSecurityPolicyCon.DbPolicy(RSqlSecurityPolicy::ESchemaPolicy));
       
   757 	StoreSecurityPolicyL(stmtHandle, KDbObjType, KNullDesC, RSqlSecurityPolicy::EReadPolicy, aSecurityPolicyCon.DbPolicy(RSqlSecurityPolicy::EReadPolicy));
       
   758 	StoreSecurityPolicyL(stmtHandle, KDbObjType, KNullDesC, RSqlSecurityPolicy::EWritePolicy, aSecurityPolicyCon.DbPolicy(RSqlSecurityPolicy::EWritePolicy));
       
   759 	//Store database objects security policies into the table
       
   760 	TSqlSecurityPolicyIterator it(aSecurityPolicyCon);
       
   761 	RSqlSecurityPolicy::TObjectType objectType;
       
   762 	TPtrC objectName;
       
   763 	RSqlSecurityPolicy::TPolicyType policyType;
       
   764 	TSecurityPolicy policy;
       
   765 	while(it.Next(objectType, objectName, policyType, policy))
       
   766 		{
       
   767 		if(objectType == RSqlSecurityPolicy::ETable && ::IsSystemTableName(objectName))
       
   768 	   		{
       
   769 	   		//Clients are not allowed to put system table names in the RSqlSecurityPolicy container.
       
   770 			__SQLLEAVE(KErrArgument);		   			
       
   771 	   		}
       
   772 		StoreSecurityPolicyL(stmtHandle, objectType, objectName, policyType, policy);
       
   773 		}
       
   774 	CleanupStack::PopAndDestroy();//cleanupItem (statement handle)
       
   775 	}
       
   776 
       
   777 /**
       
   778 Stores a security policy object in the security policies table.
       
   779 
       
   780 @param aStmtHandle Statement handle.
       
   781 @param aObjType Database object type: default security policies, database security policies, table security policies
       
   782 @param aObjName Database object name. It is expected to be a non-empty string only for tables.
       
   783 @param aPolicyType Security policy type: schema, write, read.
       
   784 @param aPolicy Security policy object.
       
   785 
       
   786 @leave KErrNoMemory, an out of memory condition has occurred;
       
   787                   	 Note that the function may also leave with some other database specific 
       
   788                   	 errors categorised as ESqlDbError, and other system-wide error codes.
       
   789 
       
   790 @panic SqlDb 4 In _DEBUG mode if aHandle argument is NULL.
       
   791 */
       
   792 void TSqlDbSysSettings::StoreSecurityPolicyL(sqlite3_stmt* aStmtHandle, TInt aObjType, const TDesC& aObjName, 
       
   793 											 TInt aPolicyType, const TSecurityPolicy& aPolicy)
       
   794 	{
       
   795 	__SQLASSERT(aStmtHandle != NULL, ESqlPanicBadArgument);
       
   796 	__SQLLEAVE_IF_ERROR(::StmtReset(aStmtHandle));
       
   797 	__SQLLEAVE_IF_ERROR(BindSecurityPolicyPrm(aStmtHandle, aObjType, aObjName, aPolicyType, aPolicy));
       
   798 	__SQLLEAVE_IF_ERROR(::StmtExec(aStmtHandle));
       
   799 	}
       
   800 
       
   801 /**
       
   802 Binds the parameter values for the insert SQL statement for security policies table.
       
   803 
       
   804 @param aStmtHandle Statement handle.
       
   805 @param aObjType Database object type: default security policy, database security policies, table security policies
       
   806 @param aObjName Database object name. It is expected to be a non-empty string only for tables.
       
   807 @param aPolicyType Security policy type: schema, write, read.
       
   808 @param aPolicy Security policy object.
       
   809 
       
   810 @see TSqlDbSysSettings::StoreSecurityPolicyL()
       
   811 
       
   812 @panic SqlDb 4 In _DEBUG mode if aHandle argument is NULL.
       
   813 */
       
   814 TInt TSqlDbSysSettings::BindSecurityPolicyPrm(sqlite3_stmt* aStmtHandle, TInt aObjType, const TDesC& aObjName, 
       
   815 												  TInt aPolicyType, const TSecurityPolicy& aPolicy)
       
   816 	{
       
   817 	(void)sqlite3SymbianLastOsError();//clear last OS error
       
   818 	TInt err = sqlite3_bind_int(aStmtHandle, KObjTypePrmIdx, aObjType);
       
   819 	if(err == SQLITE_OK)
       
   820 		{
       
   821 		err = sqlite3_bind_text16(aStmtHandle, KObjNamePrmIdx, aObjName.Ptr(), aObjName.Length() * sizeof(TText), SQLITE_STATIC);
       
   822 		if(err == SQLITE_OK)
       
   823 			{
       
   824 			err = sqlite3_bind_int(aStmtHandle, KObjPolicyTypePrmIdx, aPolicyType);
       
   825 			if(err == SQLITE_OK)
       
   826 				{
       
   827 				TPtrC8 policyData(aPolicy.Package());
       
   828 				err = sqlite3_bind_blob(aStmtHandle, KObjPolicyDataPrmIdx, policyData.Ptr(), policyData.Length(), SQLITE_STATIC);
       
   829 				}
       
   830 			}
       
   831 		}
       
   832 	return ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
       
   833 	}
       
   834 
       
   835 /**
       
   836 Reads a record from security policies table.
       
   837 
       
   838 @param aStmtHandle Statement handle. It cannot be NULL.
       
   839 @param aSecurityPolicy Security policies container.
       
   840 @param aObjType Output parameter, will be initialized with the database object type: KDefaultObjType,
       
   841 				KDbObjType, RSqlSecurityPolicy::ETable.
       
   842 @param aObjName Output parameter, database object name (for example, table name), which is protected by the
       
   843 				current security policy.
       
   844 @param aPolicyType Output parameter, will be initialized with the database policy type: RSqlSecurityPolicy::EReadPolicy,
       
   845 				   RSqlSecurityPolicy::EWritePolicy, RSqlSecurityPolicy::ESchemaPolicy.
       
   846 @return The created security policy object.
       
   847 
       
   848 @leave KErrGeneral, invalid security policy data;
       
   849 	   KErrNoMemory, Out of memory.
       
   850 */
       
   851 TSecurityPolicy TSqlDbSysSettings::ReadCurrSecurityPolicyL(sqlite3_stmt* aStmtHandle, TInt& aObjType, 
       
   852 														   TPtrC& aObjName, TInt& aPolicyType)
       
   853 	{
       
   854 	__SQLASSERT(aStmtHandle != NULL, ESqlPanicBadArgument);
       
   855 	aObjType = sqlite3_column_int(aStmtHandle, KObjTypeColIdx);
       
   856 	TInt len = (TUint)sqlite3_column_bytes16(aStmtHandle, KObjNameColIdx) / sizeof(TUint16);
       
   857 	const void* text = sqlite3_column_text16(aStmtHandle, KObjNameColIdx);
       
   858 	aObjName.Set(reinterpret_cast <const TUint16*> (text), len);
       
   859 	aPolicyType = sqlite3_column_int(aStmtHandle, KObjPolicyTypeColIdx);
       
   860 	len = sqlite3_column_bytes(aStmtHandle, KObjPolicyDataColIdx);
       
   861 	if(len != sizeof(TSecurityPolicy))
       
   862 		{
       
   863 		//Check if the error is "out of memory" (which may happen when retrieving text column data
       
   864 		//and the column encoding is different, in which case  the column text has to be converted 
       
   865 		//and a new block of memory has to be allocated for the conversion).
       
   866 		TInt err2 = ::StmtReset(aStmtHandle);
       
   867 		__SQLLEAVE(err2 == KErrNoMemory ? KErrNoMemory : KErrGeneral);
       
   868 		}
       
   869 	const void* data = sqlite3_column_blob(aStmtHandle, KObjPolicyDataColIdx);
       
   870 	TSecurityPolicy policy;
       
   871 	policy.Set(TPtrC8(reinterpret_cast <const TUint8*> (data), len));
       
   872 	return policy;
       
   873 	}
       
   874 
       
   875 /**
       
   876 Stores the default security policy into aSecurityPolicyCon container.
       
   877 Initialises all database security policies not set yet with the default security policy.
       
   878 
       
   879 @param aSecurityPolicyCon Security policies container.
       
   880 @param aPolicy Default security policy object
       
   881 @param aDbPolicySetFlag Bit flag. Keeps information which database security policies are set and which aren't.
       
   882 
       
   883 @leave See CSqlSecurityPolicy::SetDbPolicy() return values.
       
   884 @see CSqlSecurityPolicy::SetDbPolicy()
       
   885 */
       
   886 void TSqlDbSysSettings::StoreDefaultSecurityPolicyL(CSqlSecurityPolicy& aSecurityPolicyCon, 
       
   887 													const TSecurityPolicy& aPolicy, TInt aDbPolicySetFlag)
       
   888 	{
       
   889 	aSecurityPolicyCon.SetDefaultPolicy(aPolicy);
       
   890 	if(!(aDbPolicySetFlag & (1 << RSqlSecurityPolicy::ESchemaPolicy)))
       
   891 		{
       
   892 		__SQLLEAVE_IF_ERROR(aSecurityPolicyCon.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, aPolicy));
       
   893 		}
       
   894 	if(!(aDbPolicySetFlag & (1 << RSqlSecurityPolicy::EReadPolicy)))
       
   895 		{
       
   896 		__SQLLEAVE_IF_ERROR(aSecurityPolicyCon.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, aPolicy));
       
   897 		}
       
   898 	if(!(aDbPolicySetFlag & (1 << RSqlSecurityPolicy::EWritePolicy)))
       
   899 		{
       
   900 		__SQLLEAVE_IF_ERROR(aSecurityPolicyCon.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, aPolicy));
       
   901 		}
       
   902 	}
       
   903 
       
   904 /**
       
   905 Stores a database security policy into aSecurityPolicyCon container.
       
   906 
       
   907 @param aSecurityPolicyCon Security policies container.
       
   908 @param aPolicyType Database policy type: RSqlSecurityPolicy::EReadPolicy,
       
   909 				   RSqlSecurityPolicy::EWritePolicy, RSqlSecurityPolicy::ESchemaPolicy.
       
   910 @param aPolicy Database security policy object
       
   911 @param aDbPolicySetFlag Bit flag. Keeps information which database security policies are set and which aren't.
       
   912 						The parameter value may change if some of the database policies are set by
       
   913 						StoreDbSecurityPolicyL().
       
   914 
       
   915 @leave KErrGeneral Invalid security policy type or the corresponding database security policy has been set already.
       
   916 */
       
   917 void TSqlDbSysSettings::StoreDbSecurityPolicyL(CSqlSecurityPolicy& aSecurityPolicyCon, TInt aPolicyType,
       
   918 											   const TSecurityPolicy& aPolicy, TInt& aDbPolicySetFlag)
       
   919 	{
       
   920 	if(aPolicyType < (TInt)RSqlSecurityPolicy::ESchemaPolicy || aPolicyType > (TInt)RSqlSecurityPolicy::EWritePolicy)
       
   921 		{
       
   922 		__SQLLEAVE(KErrGeneral);
       
   923 		}
       
   924 	if(aDbPolicySetFlag & (1 << aPolicyType))
       
   925 		{
       
   926 		__SQLLEAVE(KErrGeneral);
       
   927 		}
       
   928 	__SQLLEAVE_IF_ERROR(aSecurityPolicyCon.SetDbPolicy(static_cast <RSqlSecurityPolicy::TPolicyType> (aPolicyType), aPolicy));
       
   929 	aDbPolicySetFlag |= (1 << aPolicyType);
       
   930 	}
       
   931 
       
   932 /**
       
   933 Stores a database object security policy into aSecurityPolicyCon container.
       
   934 
       
   935 @param aSecurityPolicyCon Security policies container.
       
   936 @param aObjType Database object type: RSqlSecurityPolicy::ETable.
       
   937 @param aObjName Database object name (for example, table name), which is protected by the current security policy.
       
   938 @param aPolicyType Database policy type: RSqlSecurityPolicy::EReadPolicy,
       
   939 				   RSqlSecurityPolicy::EWritePolicy, RSqlSecurityPolicy::ESchemaPolicy.
       
   940 @param aPolicy Database security policy object
       
   941 @param aDbPolicySetFlag Bit flag. Keeps information which database security policies are set and which aren't.
       
   942 						The parameter value may change if some of the database policies are set by
       
   943 						StoreDbSecurityPolicyL().
       
   944 
       
   945 @leave KErrGeneral Invalid security policy type or invalid database object name length.
       
   946 */
       
   947 void TSqlDbSysSettings::StoreDbObjSecurityPolicyL(CSqlSecurityPolicy& aSecurityPolicyCon, 
       
   948 							   					  TInt aObjType, const TDesC& aObjName,
       
   949 							   					  TInt aPolicyType, const TSecurityPolicy& aPolicy)
       
   950 	{
       
   951 	if(aPolicyType < (TInt)RSqlSecurityPolicy::EReadPolicy || aPolicyType > (TInt)RSqlSecurityPolicy::EWritePolicy)
       
   952 		{
       
   953 		__SQLLEAVE(KErrGeneral);
       
   954 		}
       
   955 	if(aObjName.Length() < 1)
       
   956 		{
       
   957 		__SQLLEAVE(KErrGeneral);
       
   958 		}
       
   959 	__SQLLEAVE_IF_ERROR(aSecurityPolicyCon.SetPolicy(static_cast<RSqlSecurityPolicy::TObjectType> (aObjType), 
       
   960 							aObjName, static_cast <RSqlSecurityPolicy::TPolicyType> (aPolicyType), aPolicy));
       
   961 	}
       
   962 
       
   963 /**
       
   964 Returns true if settigns table exists. 
       
   965 (Non-secure databases prior version 3 don't have settings table)
       
   966 
       
   967 @param aDbName Logical database name: "main" for the main database or attached database name.
       
   968 */
       
   969 TBool TSqlDbSysSettings::SettingsTableExistsL(const TDesC& aDbName)
       
   970 	{
       
   971 	HBufC* buf = HBufC::NewLC(sizeof(KSettingsTableCheckSql) + aDbName.Length());
       
   972 	TPtr sql = buf->Des();
       
   973 	sql.Format(KSettingsTableCheckSql(), &aDbName);
       
   974 	sqlite3_stmt* stmtHandle = ::StmtPrepare16L(iDbHandle, sql);
       
   975 	CleanupStack::PushL(TCleanupItem(&FinalizeStatementHandle, stmtHandle));
       
   976 	TInt rc = ::StmtNext(stmtHandle);
       
   977 	CleanupStack::PopAndDestroy();//cleanupItem (statement handle)
       
   978 	CleanupStack::PopAndDestroy(buf);
       
   979 	__SQLLEAVE_IF_ERROR(rc);
       
   980 	return rc == KSqlAtRow;
       
   981 	}
       
   982 
       
   983 /**
       
   984 Returns true if at least one index using aCollationName exists.
       
   985 
       
   986 @param aDbName Logical database name: "main" for the main database or attached database name,
       
   987 @param aCollationName SQLITE collation name.
       
   988 */
       
   989 TBool TSqlDbSysSettings::IndexExistsL(const TDesC& aDbName, const TDesC& aCollationName)
       
   990 	{
       
   991 	//KGetIndexSql will contain '%<CollationName>%' search pattern, while Symbian OS search patterns use '*' symbol by default.
       
   992 	//This time the '%' is OK because the serach is performed in the SQLITE master table and before installing the
       
   993 	//user-defined Like() function.
       
   994 	HBufC* buf = HBufC::NewLC(sizeof(KGetIndexSql) + aDbName.Length() + aCollationName.Length());
       
   995 	TPtr sql = buf->Des();
       
   996 	sql.Format(KGetIndexSql(), &aDbName, &aCollationName);
       
   997 	sqlite3_stmt* stmtHandle = ::StmtPrepare16L(iDbHandle, sql);
       
   998 	CleanupStack::PushL(TCleanupItem(&FinalizeStatementHandle, stmtHandle));
       
   999 	TInt rc = ::StmtNext(stmtHandle);
       
  1000 	CleanupStack::PopAndDestroy(2);//buf, cleanupItem (statement handle)
       
  1001 	__SQLLEAVE_IF_ERROR(rc);
       
  1002 	return rc == KSqlAtRow;
       
  1003 	}