srsf/sisrscontrollerplugin/src/sicommondb.cpp
branchRCL_3
changeset 19 e36f3802f733
equal deleted inserted replaced
18:cad71a31b7fc 19:e36f3802f733
       
     1 /*
       
     2 * Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class is the baseclass for all SI Controller Plugin DB
       
    15 *               classes. It implements the common database functionalities.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "sicommondb.h"
       
    23 #include "rubydebug.h"
       
    24 
       
    25 // CONSTANTS
       
    26 
       
    27 // Name of the DB lock mutex
       
    28 _LIT( KLockMutex, "SIGRAMMAR" );
       
    29 
       
    30 // ============================ MEMBER FUNCTIONS ===============================
       
    31 
       
    32 // -----------------------------------------------------------------------------
       
    33 // CSICommonDB::CSICommonDB
       
    34 // C++ default constructor can NOT contain any code, that
       
    35 // might leave.
       
    36 // -----------------------------------------------------------------------------
       
    37 //
       
    38 CSICommonDB::CSICommonDB( RDbNamedDatabase& aDatabase, 
       
    39                           RDbs& aDbSession, TInt aDrive )
       
    40 : iDb( aDatabase ),
       
    41   iDbSession( aDbSession ),
       
    42   iDrive( aDrive )
       
    43     {
       
    44     
       
    45     TInt err = iMutex.OpenGlobal( KLockMutex );
       
    46     if ( err != KErrNone )
       
    47         {
       
    48         RUBY_DEBUG0( "CSICommonDB::CSICommonDB Creating new global mutex" );
       
    49         iMutex.CreateGlobal( KLockMutex );
       
    50         }
       
    51     else
       
    52         {
       
    53         RUBY_DEBUG0( "CSICommonDB::CSICommonDB Using existing global mutex" );
       
    54         }
       
    55     
       
    56     }
       
    57 
       
    58 // -----------------------------------------------------------------------------
       
    59 // CSICommonDB::CSICommonDB
       
    60 // Destructor 
       
    61 // -----------------------------------------------------------------------------
       
    62 //
       
    63 CSICommonDB::~CSICommonDB()
       
    64     {
       
    65     if ( iMutex.IsHeld() )
       
    66         {
       
    67         iMutex.Signal();
       
    68         }
       
    69     iMutex.Close();    
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CSICommonDB::CheckIDTableL
       
    74 // Each of controller's database files has an ID table.  If the database has no
       
    75 // table, this is the first time the database is open, so the ID table is created.
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 void CSICommonDB::CreateIDTableL( const TDesC& aIdTable,
       
    79                                   const TDesC& aIdColumn,
       
    80                                   const TDesC& aIndex )
       
    81     {
       
    82     RUBY_DEBUG_BLOCK( "CSICommonDB::CheckIDTableL - create ID table" );
       
    83     
       
    84     TBuf<150> KSQLStatement;
       
    85     // Declare a literal string to hold the SQL statement
       
    86     // CREATE TABLE aIdTable (aIdColumn COUNTER, KClientUidColumn INTEGER NOT NULL,
       
    87     // KCounterColumn INTEGER NOT NULL, KUsedColumn BIT NOT NULL)
       
    88     _LIT(KSQLCreate1, "CREATE TABLE ");
       
    89     _LIT(KSQLCreate2, " COUNTER, ");
       
    90     _LIT(KSQLCreate3, " INTEGER NOT NULL, ");
       
    91     _LIT(KSQLCreate4, " BIT NOT NULL)");
       
    92     
       
    93     KSQLStatement = KSQLCreate1;
       
    94     KSQLStatement.Append(aIdTable);
       
    95     KSQLStatement.Append(KOpenParen);
       
    96     KSQLStatement.Append(aIdColumn);
       
    97     KSQLStatement.Append(KSQLCreate2);
       
    98     KSQLStatement.Append(KClientUidColumn);
       
    99     KSQLStatement.Append(KSQLCreate3);
       
   100     KSQLStatement.Append(KCounterColumn);
       
   101     KSQLStatement.Append(KSQLCreate3);
       
   102     KSQLStatement.Append(KUsedColumn);
       
   103     KSQLStatement.Append(KSQLCreate4);
       
   104     
       
   105     User::LeaveIfError(iDb.Execute(KSQLStatement));
       
   106     
       
   107     // Create an index on the 'Id' column to ensure 'Id' values are unique
       
   108     // CREATE UNIQUE INDEX aIndex ON aIdTable (aIdColumn)
       
   109     _LIT(KSQLIndex1, "CREATE UNIQUE INDEX ");
       
   110     _LIT(KSQLIndex2, " ON ");
       
   111     
       
   112     KSQLStatement = KSQLIndex1;
       
   113     KSQLStatement.Append(aIndex);
       
   114     KSQLStatement.Append(KSQLIndex2);
       
   115     KSQLStatement.Append(aIdTable);
       
   116     KSQLStatement.Append(KOpenParen);
       
   117     KSQLStatement.Append(aIdColumn);
       
   118     KSQLStatement.Append(KCloseParen);
       
   119     
       
   120     User::LeaveIfError(iDb.Execute(KSQLStatement));
       
   121     }
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // CSICommonDB::CreateNewIDL
       
   125 // This function first checks to see if there is an "unused" ID.  If one is not
       
   126 // found, it creates a new row in the table for a new ID.
       
   127 // -----------------------------------------------------------------------------
       
   128 //
       
   129 TUint32 CSICommonDB::CreateNewIDL(
       
   130 	const TDesC& aTableName,
       
   131 	const TDesC& aIdColumn,
       
   132 	TUid aClientUid )
       
   133     {
       
   134     RUBY_DEBUG_BLOCKL( "CSICommonDB::CreateNewIDL" );
       
   135     
       
   136 	TUint32 newID( 0 );
       
   137 	
       
   138 	iMutex.Wait();
       
   139 	
       
   140 	TRAPD( error, newID = DoCreateNewIDL( aTableName, aIdColumn, aClientUid ) );
       
   141 	
       
   142 	iMutex.Signal();
       
   143 	
       
   144     User::LeaveIfError( error );
       
   145 
       
   146 	return newID;
       
   147 	}
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // CSICommonDB::CountL
       
   151 // This function first searches the row with aKey and returns the counter value
       
   152 // given that the row is set as "used".
       
   153 // -----------------------------------------------------------------------------
       
   154 //
       
   155 TInt CSICommonDB::CountL( const TDesC& aTableName, const TDesC& aIndex,
       
   156                           TUint aKey )
       
   157 	{
       
   158     RUBY_DEBUG_BLOCK( "CSICommonDB::CountL" );
       
   159 	RDbTable dbTable;		// Provides access to table data as a rowset
       
   160 	TInt count = 0;
       
   161 
       
   162 	// Open model table
       
   163 	User::LeaveIfError(dbTable.Open(iDb, aTableName, RDbTable::EReadOnly));
       
   164 	CleanupClosePushL(dbTable);
       
   165 	User::LeaveIfError(dbTable.SetIndex(aIndex));
       
   166 
       
   167 	TDbSeekKey key(aKey);
       
   168 	// Return true, if a matching row found
       
   169 	if ( dbTable.SeekL(key) )
       
   170 		{
       
   171 		dbTable.GetL();
       
   172 		// Get column set for column ordinals
       
   173 		CDbColSet* columns = dbTable.ColSetL();
       
   174 		TDbColNo counter_col = columns->ColNo(KCounterColumn);
       
   175 		TDbColNo used_col = columns->ColNo(KUsedColumn);
       
   176 		delete columns;
       
   177 
       
   178 		// Check if this row is currently in use
       
   179 		TBool used = dbTable.ColInt(used_col);
       
   180 		if ( used )
       
   181 			{
       
   182 			count = dbTable.ColInt(counter_col);
       
   183 			}
       
   184 		else
       
   185 			{
       
   186             RUBY_DEBUG1( "CSICommonDB::CountL - key=%d is unused", aKey );
       
   187 			User::Leave(KErrNotFound);
       
   188 			}
       
   189 		}
       
   190 	else
       
   191 		{
       
   192         RUBY_DEBUG1( "CSICommonDB::CountL - can't find key=%d", aKey );
       
   193 		User::Leave(KErrNotFound);
       
   194 		}
       
   195 
       
   196     // Cleanup dbTable
       
   197     CleanupStack::PopAndDestroy();
       
   198 	return count;
       
   199 	}
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CSICommonDB::CreateDatabaseL
       
   203 // Creates a database file if one does not exist yet.
       
   204 // -----------------------------------------------------------------------------
       
   205 //
       
   206 TBool CSICommonDB::FindUnusedIDL(
       
   207 	RDbTable& aDbTable )
       
   208 	{
       
   209 	TBuf<30> KSQLQuery;
       
   210 	// Declare a literal string to hold the SQL search-condition for 'unused' row
       
   211 	// KUsedColumn = KNotUsed
       
   212 	KSQLQuery = KUsedColumn;
       
   213 	KSQLQuery.Append(KEqual);
       
   214 	KSQLQuery.AppendNum(KNotUsed);
       
   215 
       
   216 	// Return true, if the table is not empty and a matching row found
       
   217 	return (aDbTable.FirstL()  &&  aDbTable.FindL(RDbTable::EForwards, TDbQuery(KSQLQuery)) != KErrNotFound);
       
   218 	}
       
   219 
       
   220 // -----------------------------------------------------------------------------
       
   221 // CSICommonDB::GetAllClientIDsL
       
   222 // This function returns all Ids in the specified table that belong to the specified client.
       
   223 // -----------------------------------------------------------------------------
       
   224 //
       
   225 void CSICommonDB::GetAllClientIDsL(
       
   226 	const TDesC& aIdTable,
       
   227 	const TDesC& aIdColumn,
       
   228 	TUid aClientUid,
       
   229 	RArray<TUint32>& aIDs )
       
   230 	{
       
   231 	CleanupClosePushL( aIDs ); 
       
   232 	
       
   233 	TBuf<100> KSQLStatement;
       
   234 	// Declare a literal string to hold the SQL statement
       
   235 	// SELECT aIdColumn, KUsedColumn FROM aIdTable WHERE KClientUidColumn = uid
       
   236 	// ORDER BY aIdColumn
       
   237 	_LIT(KSQLSelect1, "SELECT ");
       
   238 	_LIT(KSQLSelect2, " FROM ");
       
   239 	_LIT(KSQLSelect3, " WHERE ");
       
   240 	_LIT(KSQLSelect4, " ORDER BY ");
       
   241 
       
   242 	KSQLStatement = KSQLSelect1;
       
   243 	KSQLStatement.Append(aIdColumn);
       
   244 	KSQLStatement.Append(KNext);
       
   245 	KSQLStatement.Append(KUsedColumn);
       
   246 	KSQLStatement.Append(KSQLSelect2);
       
   247 	KSQLStatement.Append(aIdTable);
       
   248 	KSQLStatement.Append(KSQLSelect3);
       
   249 	KSQLStatement.Append(KClientUidColumn);
       
   250 	KSQLStatement.Append(KEqual);
       
   251 	KSQLStatement.AppendNum((TInt) aClientUid.iUid);
       
   252 	KSQLStatement.Append(KSQLSelect4);
       
   253 	KSQLStatement.Append(aIdColumn);
       
   254 
       
   255 	RDbView view;
       
   256 	CleanupClosePushL(view);
       
   257 	User::LeaveIfError(view.Prepare(iDb, TDbQuery(KSQLStatement, EDbCompareNormal)));
       
   258 	User::LeaveIfError(view.EvaluateAll());
       
   259 
       
   260 	// Get column set for column ordinals
       
   261     CDbColSet* columns = view.ColSetL();
       
   262     TDbColNo id_col = columns->ColNo(aIdColumn);
       
   263 	TDbColNo used_col = columns->ColNo(KUsedColumn);
       
   264 	delete columns;
       
   265 
       
   266 	TUint32 id;
       
   267 	TBool used;
       
   268 	// After evaluation, the first call to NextL() is equivalent to FirstL()
       
   269 	while ( view.NextL() )
       
   270 		{
       
   271 		// Retrieve the current row
       
   272 		view.GetL();
       
   273 		// Check if this row is currently in use
       
   274 		used = view.ColInt(used_col);
       
   275 		if ( used )
       
   276 			{
       
   277 			id = view.ColUint32(id_col);
       
   278 			User::LeaveIfError(aIDs.Append(id));
       
   279 			}
       
   280 		}
       
   281 
       
   282 	// Cleanup view
       
   283     CleanupStack::PopAndDestroy();
       
   284     CleanupStack::Pop();
       
   285 	}
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 // CSICommonDB::GetAllIDsL
       
   289 // This function returns all Ids in the specified table.
       
   290 // -----------------------------------------------------------------------------
       
   291 //
       
   292 void CSICommonDB::GetAllIDsL(
       
   293 	const TDesC& aIdTable,
       
   294 	const TDesC& aIdColumn,
       
   295 	RArray<TUint32>& aIDs )
       
   296 	{
       
   297 	CleanupClosePushL( aIDs ); 
       
   298 	
       
   299 	TBuf<100> KSQLStatement;
       
   300 	// Declare a literal string to hold the SQL statement
       
   301 	// SELECT aIdColumn FROM aIdTable WHERE KUsedColumn = KUsed
       
   302 	// ORDER BY aIdColumn
       
   303 	_LIT(KSQLSelect1, "SELECT ");
       
   304 	_LIT(KSQLSelect2, " FROM ");
       
   305 	_LIT(KSQLSelect3, " WHERE ");
       
   306 	_LIT(KSQLSelect4, " ORDER BY ");
       
   307 
       
   308 	KSQLStatement = KSQLSelect1;
       
   309 	KSQLStatement.Append(aIdColumn);
       
   310 	KSQLStatement.Append(KSQLSelect2);
       
   311 	KSQLStatement.Append(aIdTable);
       
   312 	KSQLStatement.Append(KSQLSelect3);
       
   313 	KSQLStatement.Append(KUsedColumn);
       
   314 	KSQLStatement.Append(KEqual);
       
   315 	KSQLStatement.AppendNum(KUsed);
       
   316 	KSQLStatement.Append(KSQLSelect4);
       
   317 	KSQLStatement.Append(aIdColumn);
       
   318 
       
   319 	RDbView view;
       
   320 	CleanupClosePushL(view);
       
   321 	User::LeaveIfError(view.Prepare(iDb, TDbQuery(KSQLStatement, EDbCompareNormal)));
       
   322 	User::LeaveIfError(view.EvaluateAll());
       
   323 
       
   324 	// Get column set for column ordinals
       
   325     CDbColSet* columns = view.ColSetL();
       
   326     TDbColNo id_col = columns->ColNo(aIdColumn);
       
   327 	delete columns;
       
   328 
       
   329 	TUint32 id;
       
   330 	// After evaluation, the first call to NextL() is equivalent to FirstL()
       
   331 	while ( view.NextL() )
       
   332 		{
       
   333 		// Retrieve the current row
       
   334 		view.GetL();
       
   335 		id = view.ColUint32(id_col);
       
   336 		User::LeaveIfError(aIDs.Append(id));
       
   337 		}
       
   338 
       
   339 	// Cleanup view
       
   340     CleanupStack::PopAndDestroy();
       
   341     CleanupStack::Pop(); 
       
   342 	}
       
   343 
       
   344 // -----------------------------------------------------------------------------
       
   345 // CSICommonDB::IsValidL
       
   346 // Checks to see if aKey exists in the table and that it's set to "used".
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 TBool CSICommonDB::IsValidL( const TDesC& aTableName, const TDesC& aIndex,
       
   350                              TUint aKey )
       
   351 	{
       
   352     RUBY_DEBUG_BLOCK( "CSICommonDB::IsValidL" );
       
   353 	RDbTable dbTable;		// Provides access to table data as a rowset
       
   354 	TBool valid = EFalse;
       
   355 
       
   356 	// Open table
       
   357 	User::LeaveIfError(dbTable.Open(iDb, aTableName, RDbTable::EReadOnly));
       
   358 	CleanupClosePushL(dbTable);
       
   359 	User::LeaveIfError(dbTable.SetIndex(aIndex));
       
   360 
       
   361 	TDbSeekKey key(aKey);
       
   362 	// Return true, if a matching row found
       
   363 	if ( dbTable.SeekL(key) )
       
   364 		{
       
   365         RUBY_DEBUG1( "CSICommonDB::IsValidL - %d is found", aKey );
       
   366 		dbTable.GetL();
       
   367 		// Get column set for column ordinals
       
   368 		CDbColSet* columns = dbTable.ColSetL();
       
   369 		TDbColNo used_col = columns->ColNo(KUsedColumn);
       
   370 		delete columns;
       
   371 
       
   372 		// Check if this row is currently in use
       
   373 		valid = dbTable.ColInt(used_col);
       
   374 		}
       
   375 
       
   376     // Cleanup dbTable
       
   377     CleanupStack::PopAndDestroy();
       
   378 	return valid;
       
   379 	}
       
   380 
       
   381 // -----------------------------------------------------------------------------
       
   382 // CSICommonDB::ReleaseIdL
       
   383 // Releases the ID by marking it as "unused".
       
   384 // -----------------------------------------------------------------------------
       
   385 //
       
   386 void CSICommonDB::ReleaseIdL(
       
   387 	const TDesC& aTableName,
       
   388 	const TDesC& aIdColumn,
       
   389 	TUint32 aId )
       
   390 	{
       
   391 	RUBY_DEBUG_BLOCKL( "CSICommonDB::ReleaseIdL" );
       
   392     	
       
   393 	iMutex.Wait();
       
   394 	
       
   395 	TRAPD( error, DoReleaseIdL( aTableName, aIdColumn, aId ) );
       
   396 	
       
   397 	iMutex.Signal();
       
   398 	
       
   399     User::LeaveIfError( error );
       
   400 	}
       
   401 
       
   402 // -----------------------------------------------------------------------------
       
   403 // CSICommonDB::UpdateCounterL
       
   404 // Updates the counter value of the specified row.
       
   405 // -----------------------------------------------------------------------------
       
   406 //
       
   407 void CSICommonDB::UpdateCounterL( const TDesC& aTableName, const TDesC& aIndex,
       
   408                                   TUint aKey, TBool aIncrement )
       
   409 	{
       
   410     RUBY_DEBUG_BLOCK( "CSICommonDB::UpdateCounterL" );
       
   411 	RDbTable dbTable;		// Provides access to table data as a rowset
       
   412 
       
   413 	// Open table
       
   414 	User::LeaveIfError(dbTable.Open(iDb, aTableName, RDbTable::EUpdatable));
       
   415 	CleanupClosePushL(dbTable);
       
   416 	User::LeaveIfError(dbTable.SetIndex(aIndex));
       
   417 
       
   418 	TDbSeekKey key(aKey);
       
   419 	// Return true, if a matching row found
       
   420 	if ( dbTable.SeekL(key) )
       
   421 		{
       
   422 		dbTable.GetL();
       
   423 		// Get column set for column ordinals
       
   424 		CDbColSet* columns = dbTable.ColSetL();
       
   425 		TDbColNo counter_col = columns->ColNo(KCounterColumn);
       
   426 		delete columns;
       
   427 
       
   428 		TInt counter = dbTable.ColInt(counter_col);
       
   429 
       
   430 		if ( aIncrement )
       
   431 			{
       
   432 			counter++;
       
   433 			}
       
   434 		else
       
   435 			{
       
   436 			counter--;
       
   437 			}
       
   438 		// Update found row
       
   439 		dbTable.UpdateL();
       
   440 		dbTable.SetColL(counter_col, counter);
       
   441 
       
   442 		// Write the updated row
       
   443 		TRAPD(err, dbTable.PutL());
       
   444 		if( err != KErrNone )
       
   445 			{
       
   446 			// Error: cancel update
       
   447 			dbTable.Cancel();
       
   448 			dbTable.Reset();
       
   449 			User::Leave(err);
       
   450 			}
       
   451 		}
       
   452 	else
       
   453 		{
       
   454         RUBY_DEBUG1( "CSICommonDB::UpdateCounterL - can't find key=%d", aKey );
       
   455 		User::Leave(KErrNotFound);
       
   456 		}
       
   457 
       
   458     // Cleanup dbTable
       
   459     CleanupStack::PopAndDestroy();
       
   460 	}
       
   461 
       
   462 // -----------------------------------------------------------------------------
       
   463 // CSICommonDB::VerifyOwnershipL
       
   464 // Checks for data ownership.
       
   465 // -----------------------------------------------------------------------------
       
   466 //
       
   467 void CSICommonDB::VerifyOwnershipL( TUid aClientUid, const TDesC& aTableName,
       
   468                                     const TDesC& aIndex, TUint aKey )
       
   469 	{
       
   470     RUBY_DEBUG_BLOCK( "CSICommonDB::VerifyOwnershipL" );
       
   471 	RDbTable dbTable;		// Provides access to table data as a rowset
       
   472 
       
   473 	// Open table
       
   474 	User::LeaveIfError(dbTable.Open(iDb, aTableName, RDbTable::EReadOnly));
       
   475 	CleanupClosePushL(dbTable);
       
   476 	User::LeaveIfError(dbTable.SetIndex(aIndex));
       
   477 
       
   478 	TDbSeekKey key(aKey);
       
   479 	// Return true, if a matching row found
       
   480 	if ( dbTable.SeekL(key) )
       
   481 		{
       
   482         RUBY_DEBUG1( "CSICommonDB::VerifyOwnershipL - %d is found", aKey );
       
   483 		dbTable.GetL();
       
   484 		// Get column set for column ordinals
       
   485 		CDbColSet* columns = dbTable.ColSetL();
       
   486 		TDbColNo client_uid_col = columns->ColNo(KClientUidColumn);
       
   487 		TDbColNo used_col = columns->ColNo(KUsedColumn);
       
   488 		delete columns;
       
   489 
       
   490 		// Check if this row is currently in use
       
   491 		TBool used = dbTable.ColInt(used_col);
       
   492 		if ( used )
       
   493 			{
       
   494 			if ( dbTable.ColInt(client_uid_col) != aClientUid.iUid )
       
   495 				{
       
   496 				User::Leave(KErrAsrDataRightViolation);
       
   497 				}
       
   498 			}
       
   499 		else
       
   500 			{
       
   501             RUBY_DEBUG1( "CSICommonDB::VerifyOwnershipL - key=%d is unused", aKey );
       
   502 			User::Leave(KErrNotFound);
       
   503 			}
       
   504 		}
       
   505 	else
       
   506 		{
       
   507         RUBY_DEBUG1( "CSICommonDB::VerifyOwnershipL - can't find key=%d", aKey );
       
   508 		User::Leave(KErrNotFound);
       
   509 		}
       
   510 
       
   511     // Cleanup dbTable
       
   512     CleanupStack::PopAndDestroy();
       
   513 	}
       
   514 
       
   515 // -----------------------------------------------------------------------------
       
   516 // CSICommonDB::DoReleaseIdL
       
   517 // Releases the ID by marking it as "unused".
       
   518 // -----------------------------------------------------------------------------
       
   519 //
       
   520 void CSICommonDB::DoReleaseIdL(
       
   521 	const TDesC& aTableName,
       
   522 	const TDesC& aIdColumn,
       
   523 	TUint32 aId )
       
   524 	{
       
   525 	TBuf<100> KSQLStatement;
       
   526 	// Declare a literal string to hold the SQL statement
       
   527 	// UPDATE aTableName SET KUsedColumn = KNotUsed WHERE aIdColumn = aId
       
   528 	_LIT(KSQLUpdate1, "UPDATE ");
       
   529 	_LIT(KSQLUpdate2, " SET ");
       
   530 	_LIT(KSQLUpdate3, " WHERE ");
       
   531 
       
   532 	KSQLStatement = KSQLUpdate1;
       
   533 	KSQLStatement.Append(aTableName);
       
   534 	KSQLStatement.Append(KSQLUpdate2);
       
   535 	KSQLStatement.Append(KUsedColumn);
       
   536 	KSQLStatement.Append(KEqual);
       
   537 	KSQLStatement.AppendNum(KNotUsed);
       
   538 	KSQLStatement.Append(KSQLUpdate3);
       
   539 	KSQLStatement.Append(aIdColumn);
       
   540 	KSQLStatement.Append(KEqual);
       
   541 	KSQLStatement.AppendNumUC(aId);
       
   542 
       
   543 	User::LeaveIfError(iDb.Execute(KSQLStatement));
       
   544 	}
       
   545 	
       
   546 // -----------------------------------------------------------------------------
       
   547 // CSICommonDB::DoCreateNewIDL
       
   548 // This function first checks to see if there is an "unused" ID.  If one is not
       
   549 // found, it creates a new row in the table for a new ID.
       
   550 // -----------------------------------------------------------------------------
       
   551 //
       
   552 TUint32 CSICommonDB::DoCreateNewIDL(
       
   553 	const TDesC& aTableName,
       
   554 	const TDesC& aIdColumn,
       
   555 	TUid aClientUid )
       
   556 	{
       
   557 	RDbTable dbTable;		// Provides access to table data as a rowset
       
   558 
       
   559 	// Open table
       
   560 	User::LeaveIfError(dbTable.Open(iDb, aTableName, RDbTable::EUpdatable));
       
   561 	CleanupClosePushL(dbTable);
       
   562 
       
   563     // Get column set for column ordinals
       
   564     CDbColSet* columns = dbTable.ColSetL();
       
   565     TDbColNo id_col = columns->ColNo(aIdColumn);
       
   566 	TDbColNo uid_col = columns->ColNo(KClientUidColumn);
       
   567     TDbColNo counter_col = columns->ColNo(KCounterColumn);
       
   568     TDbColNo used_col = columns->ColNo(KUsedColumn);
       
   569     delete columns;
       
   570 
       
   571     // Is there an unused ID?
       
   572     if( FindUnusedIDL(dbTable) )
       
   573     	{
       
   574 		// Yes, update found row
       
   575 		dbTable.UpdateL();
       
   576 		}
       
   577 	else
       
   578 		{
       
   579 		// No, insert new row
       
   580 		dbTable.InsertL();
       
   581 		}
       
   582 
       
   583 	dbTable.SetColL(uid_col, aClientUid.iUid);
       
   584 	dbTable.SetColL(counter_col, 0);
       
   585 	dbTable.SetColL(used_col, KUsed);
       
   586 
       
   587 	// Write the updated row
       
   588 	TRAPD(err, dbTable.PutL());
       
   589 	if( err != KErrNone )
       
   590 		{
       
   591 		// Error: cancel update
       
   592 		dbTable.Cancel();
       
   593 		dbTable.Reset();
       
   594 		User::Leave(err);
       
   595 		}
       
   596 
       
   597 	TUint32 newID = dbTable.ColUint32(id_col);
       
   598     // Cleanup dbTable
       
   599     CleanupStack::PopAndDestroy();
       
   600 	return newID;
       
   601 	}
       
   602 
       
   603 
       
   604 //  End of File