phonebookengines/contactsmodel/cntplsql/src/cpplcontacttable.cpp
branchRCL_3
changeset 20 f4a778e096c2
parent 0 e686773b3f54
equal deleted inserted replaced
19:5b6f26637ad3 20:f4a778e096c2
       
     1 // Copyright (c) 2007-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 //
       
    15 
       
    16 #include "pltables.h"
       
    17 #include "dbsqlconstants.h"
       
    18 #include "cntpersistenceutility.h"
       
    19 #include <cntdef.h>
       
    20 
       
    21 // forward declaration to allow this to compile. 
       
    22 // Which header file is this declared in and do we actually still need the properties here?
       
    23 class CLplContactProperties;
       
    24 
       
    25 /**
       
    26 NewL
       
    27 
       
    28 @param aDatabase A handle to the database.
       
    29 @param aProperties A contact properties object.
       
    30 
       
    31 @return A pointer to a new CPplContactTable object.
       
    32 */
       
    33 CPplContactTable* CPplContactTable::NewL(RSqlDatabase& aDatabase, CLplContactProperties& aProperties)
       
    34 	{
       
    35 	CPplContactTable* self = CPplContactTable::NewLC(aDatabase, aProperties);
       
    36 	CleanupStack::Pop(self);
       
    37 	return self;
       
    38 	}
       
    39 
       
    40 
       
    41 /**
       
    42 NewLC
       
    43 
       
    44 @param aDatabase A handle to the database.
       
    45 @param aProperties A contact properties object.
       
    46 
       
    47 @return A pointer to a new CPplContactTable object.
       
    48 */
       
    49 CPplContactTable* CPplContactTable::NewLC(RSqlDatabase& aDatabase, CLplContactProperties& aProperties)
       
    50 	{
       
    51 	CPplContactTable* self = new (ELeave) CPplContactTable(aDatabase, aProperties);
       
    52 	CleanupStack::PushL(self);
       
    53 	self->ConstructL();
       
    54 	return self;
       
    55 	}
       
    56 
       
    57 
       
    58 /**
       
    59 Set up the CCntSqlStatement objects held by the class.
       
    60 */
       
    61 void CPplContactTable::ConstructL()
       
    62 	{
       
    63 	_LIT(KOwnCardInvariant, "((((%S>>%d==%d)*%d) | ((NOT(%S>>%d==%d))*%S))<<%d)| %S");
       
    64 	
       
    65 	iCardTemplateIds = CContactIdArray::NewL();
       
    66 	
       
    67 	// Statement types
       
    68 	TCntSqlStatementType insertType(EInsert, KSqlContactTableName);
       
    69 	TCntSqlStatementType selectType(ESelect, KSqlContactTableName);
       
    70 	TCntSqlStatementType updateType(EUpdate, KSqlContactTableName);
       
    71 	TCntSqlStatementType deleteType(EDelete, KSqlContactTableName);
       
    72 
       
    73 	// Where clause
       
    74 
       
    75 	// sizes of the clause
       
    76 	const TInt KWhereClauseBufSize(KContactId().Size() + 
       
    77 		KWhereStringEqualsStringFormatText().Size() + KContactIdParam().Size() );
       
    78 
       
    79 	// for WHERE contact_id = [contact id value]
       
    80 	HBufC* whereIdClause = HBufC::NewLC(KWhereClauseBufSize);
       
    81 	whereIdClause->Des().AppendFormat(KWhereStringEqualsStringFormatText, &KContactId, 
       
    82 		&KContactIdParam );
       
    83 
       
    84 	// INSERT
       
    85 
       
    86 	// insert record into contact table
       
    87 	// For a statement in the following format:
       
    88 	// 	INSERT INTO contact 
       
    89 	//		(contact_id, template_id...[etc...], binary_fields) 
       
    90 	//		VALUES (NULL, 37, .......);
       
    91 	//
       
    92 	iInsertStmnt = TSqlProvider::GetSqlStatementL(insertType);	
       
    93 	iInsertStmnt->SetParamL(KContactId, KContactIdParam);//KNullText() );
       
    94 	iInsertStmnt->SetParamL(KContactTemplateId, KContactTemplateIdParam);
       
    95 	iInsertStmnt->SetParamL(KContactTypeFlags, KContactTypeFlagsParam);
       
    96 	iInsertStmnt->SetParamL(KContactAccessCount, KContactAccessCountParam);
       
    97 	iInsertStmnt->SetParamL(KContactCreationDate, KContactCreationDateParam);
       
    98 	iInsertStmnt->SetParamL(KContactLastModified, KContactLastModifiedParam);
       
    99 	iInsertStmnt->SetParamL(KContactGuidString, KContactGuidStringParam);
       
   100 	iInsertStmnt->SetParamL(KContactFirstName, KContactFirstNameParam);
       
   101 	iInsertStmnt->SetParamL(KContactLastName, KContactLastNameParam);
       
   102 	iInsertStmnt->SetParamL(KContactCompanyName, KContactCompanyNameParam);
       
   103 	iInsertStmnt->SetParamL(KContactFirstNamePrn, KContactFirstNamePrnParam);
       
   104 	iInsertStmnt->SetParamL(KContactLastNamePrn, KContactLastNamePrnParam);
       
   105 	iInsertStmnt->SetParamL(KContactCompanyNamePrn, KContactCompanyNamePrnParam);
       
   106 	iInsertStmnt->SetParamL(KContactTextFieldHeader, KContactTextFieldHeaderParam);
       
   107 	iInsertStmnt->SetParamL(KContactBinaryFieldHeader, KContactBinaryFieldHeaderParam);
       
   108 	iInsertStmnt->SetParamL(KContactTextFields, KContactTextFieldsParam);
       
   109 	iInsertStmnt->SetParamL(KContactBinaryFields, KContactBinaryFieldsParam);
       
   110 
       
   111 	// SELECT
       
   112 
       
   113 	// delete select
       
   114 	// For a statement in the following format:
       
   115 	// 	SELECT type_flags, access_count, template_id FROM contact 
       
   116 	//		WHERE contact_id = [contact id value];
       
   117 	//
       
   118 	iDeleteSelectStmnt = TSqlProvider::GetSqlStatementL(selectType);	
       
   119 	iDeleteSelectStmnt->SetParamL(KContactTypeFlags, KNullDesC() );
       
   120 	iDeleteSelectStmnt->SetParamL(KContactAccessCount, KNullDesC() );
       
   121 	iDeleteSelectStmnt->SetParamL(KContactTemplateId, KNullDesC() );
       
   122 	iDeleteSelectStmnt->SetConditionL(*whereIdClause);
       
   123 
       
   124 	// UPDATE
       
   125 	
       
   126 	// update record from contact table
       
   127 	// For a statement in the following format:
       
   128 	// 	UPDATE contact SET template_id = [new template id value]
       
   129 	//      ...,
       
   130 	//      binary_fields = [new binary fields value]
       
   131 	//		WHERE contact_id = [contact id value];
       
   132 	//
       
   133 	iUpdateStmnt = TSqlProvider::GetSqlStatementL(updateType);	
       
   134 	iUpdateStmnt->SetParamL(KContactTemplateId, KContactTemplateIdParam);
       
   135 	
       
   136 	HBufC* typeFlagsParameter = HBufC::NewLC(KOwnCardInvariant().Size() + KContactTypeFlags().Size() + KContactTypeFlags().Size() + 
       
   137 			KContactTypeParam().Size() + KAttributesAndHintParam().Size() + 6*sizeof(TInt));
       
   138 	typeFlagsParameter->Des().AppendFormat(KOwnCardInvariant, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_OwnCard, EContactTypeFlags_OwnCard,
       
   139 			&KContactTypeFlags, EContactType_Shift, EContactTypeFlags_OwnCard, &KContactTypeParam, EContactType_Shift, &KAttributesAndHintParam);
       
   140 	
       
   141 	iUpdateStmnt->SetParamL(KContactTypeFlags, *typeFlagsParameter);
       
   142 	
       
   143 	iUpdateStmnt->SetParamL(KContactAccessCount, KContactAccessCountParam);
       
   144 	iUpdateStmnt->SetParamL(KContactLastModified, KContactLastModifiedParam);
       
   145 	iUpdateStmnt->SetParamL(KContactGuidString, KContactGuidStringParam);
       
   146 	iUpdateStmnt->SetParamL(KContactFirstName, KContactFirstNameParam);
       
   147 	iUpdateStmnt->SetParamL(KContactLastName, KContactLastNameParam);
       
   148 	iUpdateStmnt->SetParamL(KContactCompanyName, KContactCompanyNameParam);
       
   149 	iUpdateStmnt->SetParamL(KContactFirstNamePrn, KContactFirstNamePrnParam);
       
   150 	iUpdateStmnt->SetParamL(KContactLastNamePrn, KContactLastNamePrnParam);
       
   151 	iUpdateStmnt->SetParamL(KContactCompanyNamePrn, KContactCompanyNamePrnParam);
       
   152 	iUpdateStmnt->SetParamL(KContactTextFieldHeader, KContactTextFieldHeaderParam);
       
   153 	iUpdateStmnt->SetParamL(KContactBinaryFieldHeader, KContactBinaryFieldHeaderParam);
       
   154 	iUpdateStmnt->SetParamL(KContactTextFields, KContactTextFieldsParam);
       
   155 	iUpdateStmnt->SetParamL(KContactBinaryFields, KContactBinaryFieldsParam);
       
   156 	iUpdateStmnt->SetConditionL(*whereIdClause);
       
   157 
       
   158 	// type_flags update
       
   159 	// For a statement in the following format:
       
   160 	// 	UPDATE contact SET type_flags = [new type flags value]
       
   161 	//		WHERE contact_id = [contact id value];
       
   162 	//
       
   163 	iUpdateFlagsStmnt = TSqlProvider::GetSqlStatementL(updateType);	
       
   164 	iUpdateFlagsStmnt->SetParamL(KContactTypeFlags, KContactTypeFlagsParam);
       
   165 	iUpdateFlagsStmnt->SetConditionL(*whereIdClause);
       
   166 
       
   167 	// AccessCount update
       
   168 	// For a statement in the following format:
       
   169 	// 	UPDATE contact SET access_count = [new access count value]
       
   170 	//		WHERE contact_id = [contact id value];
       
   171 	//
       
   172 	iAccessCountUpdateStmnt = TSqlProvider::GetSqlStatementL(updateType);	
       
   173 	iAccessCountUpdateStmnt->SetParamL(KContactAccessCount, KContactAccessCountParam);
       
   174 	iAccessCountUpdateStmnt->SetConditionL(*whereIdClause);
       
   175 
       
   176 	// DELETE
       
   177 
       
   178 	// delete record from contact table
       
   179 	// For a statement in the following format:
       
   180 	// 	DELETE FROM contact WHERE contact_id = [contact id value];
       
   181 	//
       
   182 	iDeleteStmnt = TSqlProvider::GetSqlStatementL(deleteType);	
       
   183 	iDeleteStmnt->SetConditionL(*whereIdClause);
       
   184 
       
   185 	// Set up the field lookup table hash map
       
   186 	iFieldMap.InsertL(KUidContactFieldGivenNameValue, KContactFirstNameParam() );
       
   187 	iFieldMap.InsertL(KUidContactFieldGivenNamePronunciationValue, KContactFirstNamePrnParam() );
       
   188 	iFieldMap.InsertL(KUidContactFieldFamilyNameValue, KContactLastNameParam() );
       
   189 	iFieldMap.InsertL(KUidContactFieldFamilyNamePronunciationValue, KContactLastNamePrnParam() );
       
   190 	iFieldMap.InsertL(KUidContactFieldCompanyNameValue, KContactCompanyNameParam() );
       
   191 	iFieldMap.InsertL(KUidContactFieldCompanyNamePronunciationValue, KContactCompanyNamePrnParam() );
       
   192 
       
   193 	CleanupStack::PopAndDestroy(2, whereIdClause); //whereIdClause, typeFlagsParameter
       
   194 	}
       
   195 
       
   196 /**
       
   197 Destructor
       
   198 
       
   199 Tidy up CCntSqlStatement objects
       
   200 */
       
   201 CPplContactTable::~CPplContactTable()
       
   202 	{
       
   203 	delete iInsertStmnt;
       
   204 	delete iDeleteSelectStmnt;
       
   205 	delete iUpdateFlagsStmnt;
       
   206 	delete iUpdateStmnt;
       
   207 	delete iAccessCountUpdateStmnt;
       
   208 	delete iDeleteStmnt;
       
   209 	iFieldMap.Close();
       
   210 	delete iCardTemplateIds;
       
   211 	}
       
   212 
       
   213 
       
   214 /**
       
   215 CPplContactTable constructor
       
   216 */
       
   217 CPplContactTable::CPplContactTable(RSqlDatabase& aDatabase, CLplContactProperties& aProperties):
       
   218 	iProperties(aProperties),
       
   219 	iDatabase(aDatabase)
       
   220 	{
       
   221 	}
       
   222 
       
   223 
       
   224 /**
       
   225 Update the access count for the given template ID. If the template is marked for deletion and 
       
   226 no one is referencing it any longer, it is deleted.
       
   227 
       
   228 @param aTemplateRefId
       
   229 @param aIncrement If ETrue increase the reference count otherwise decrease the reference count.
       
   230 */
       
   231 void CPplContactTable::UpdateTemplateAccessCounterL(TContactItemId aTemplateRefId, TBool aIncrement)
       
   232 	{
       
   233 	if (aTemplateRefId == KGoldenTemplateId || aTemplateRefId == KNullContactId)
       
   234 		{
       
   235 		return;
       
   236 		}
       
   237 
       
   238 	// Get the access count and type flags for the template
       
   239 	RSqlStatement selectStmnt;
       
   240 	CleanupClosePushL(selectStmnt);
       
   241 	selectStmnt.PrepareL(iDatabase, iDeleteSelectStmnt->SqlStringL() );
       
   242 	const TInt KContactIdParamIndex(KFirstIndex); // first and only parameter in the query
       
   243 	User::LeaveIfError(selectStmnt.BindInt(KContactIdParamIndex, aTemplateRefId) );
       
   244 
       
   245 	TInt err(selectStmnt.Next() );
       
   246 	if (err != KSqlAtRow)
       
   247 		{
       
   248 		User::Leave(err);
       
   249 		}
       
   250 
       
   251 	TInt oldAccessCount(selectStmnt.ColumnInt(iDeleteSelectStmnt->ParameterIndex(KContactAccessCount() ) ) );
       
   252 	TInt newAccessCount = oldAccessCount + (aIncrement ? 1 : -1);
       
   253 	TInt typeFlags(selectStmnt.ColumnInt(iDeleteSelectStmnt->ParameterIndex(KContactTypeFlags() ) ) );
       
   254 	TInt attributes((typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift); 
       
   255 	CleanupStack::PopAndDestroy(&selectStmnt);
       
   256 
       
   257 	// set the new access count for the template
       
   258 	RSqlStatement updateStmnt;
       
   259 	CleanupClosePushL(updateStmnt);
       
   260 	updateStmnt.PrepareL(iDatabase, iAccessCountUpdateStmnt->SqlStringL() );
       
   261 	
       
   262 	const TInt KAccessCountParamIndex(KFirstParam);					// first parameter in query...
       
   263 	const TInt KTemplateIdParamIndex(KAccessCountParamIndex + 1);	// ...and the second.
       
   264 
       
   265 	User::LeaveIfError(updateStmnt.BindInt(KAccessCountParamIndex, newAccessCount) );
       
   266 	User::LeaveIfError(updateStmnt.BindInt(KTemplateIdParamIndex, aTemplateRefId) );
       
   267 	User::LeaveIfError(updateStmnt.Exec() );
       
   268 	CleanupStack::PopAndDestroy(&updateStmnt);
       
   269 
       
   270 	// should the template be deleted  -- i.e. nobody accessing it and marked as deleted?
       
   271 	if (newAccessCount <= 0 && (attributes & CContactItem::EDeleted) )
       
   272 		{
       
   273 		TBool lowDiskErr(EFalse);
       
   274 		CContactItem* templ = DeleteLC(aTemplateRefId, lowDiskErr);
       
   275 		CleanupStack::PopAndDestroy(templ);
       
   276 		if (lowDiskErr)
       
   277 			{
       
   278 			User::Leave(KErrDiskFull);
       
   279 			}
       
   280 		}
       
   281 	}
       
   282 
       
   283 void CPplContactTable::CreateInDbL(CContactItem& aItem)
       
   284 	{
       
   285 	CreateInDbL(aItem, 0);
       
   286 	}
       
   287 
       
   288 /**
       
   289 Add the given contact item to the database.
       
   290 
       
   291 @param aItem The contact item to be added to the database. 
       
   292 @param aSessionId The ID of the session that issued the request.  Used to
       
   293 prevent Phonebook Synchroniser deadlock.
       
   294 
       
   295 @return Contact item ID of the contact added to the database.
       
   296 */
       
   297 void CPplContactTable::CreateInDbL(CContactItem& aItem, TUint aSessionId)
       
   298 	{
       
   299 	if (aItem.Type() != KUidContactTemplate) // Not creating system template?
       
   300 		{
       
   301 		// Make sure the System template is loaded.
       
   302 		iProperties.SystemTemplateL();
       
   303 		}
       
   304 		
       
   305 	if (aItem.Type() == KUidContactICCEntry) 
       
   306 		{
       
   307 		TInt ret = iProperties.ContactSynchroniserL(aSessionId).ValidateWriteContact(static_cast<CContactICCEntry&>(aItem) );
       
   308 		User::LeaveIfError(ret);	
       
   309 		}
       
   310 
       
   311 	// Mark fields as template fields if the contact item is a contact card template.
       
   312 	const TBool KIsTemplateCard = (aItem.Type() == KUidContactCardTemplate);
       
   313 	CContactItemFieldSet& fieldset = aItem.CardFields();
       
   314 	for (TInt i = fieldset.Count() - 1; i >= 0; --i)
       
   315 		{
       
   316 		fieldset[i].SetTemplateField(KIsTemplateCard);
       
   317 		}
       
   318 
       
   319 	// Set iLastModified and iCreationDate to current time.
       
   320 	TTime lastModified = aItem.LastModified();
       
   321    	lastModified.UniversalTime();
       
   322    	aItem.SetLastModified(lastModified);
       
   323    	aItem.SetCreationDate(lastModified); 
       
   324 
       
   325 	// ID of newly created item obtained from autoincrementing ID column.
       
   326 	// -- get an id from the database	
       
   327 	RSqlStatement selectIdStatement;
       
   328 	CleanupClosePushL(selectIdStatement);
       
   329 		
       
   330 	User::LeaveIfError(selectIdStatement.Prepare(iDatabase, KSelectLastIdSqlStmnt()));
       
   331 
       
   332 	TInt err;
       
   333 	TInt lastId((-1));
       
   334 	if((err = selectIdStatement.Next()) == KSqlAtRow)
       
   335 		{
       
   336 		lastId = selectIdStatement.ColumnInt(0);
       
   337 		}
       
   338 
       
   339 	if(err == KSqlAtEnd)
       
   340 		{
       
   341 		lastId = -1;
       
   342 		}
       
   343 	
       
   344 	aItem.SetId(lastId + 1);
       
   345 	
       
   346 	CleanupStack::PopAndDestroy(&selectIdStatement);
       
   347 
       
   348 	// Increment Template reference counter.
       
   349 	UpdateTemplateAccessCounterL(aItem.TemplateRefId(), ETrue);
       
   350 
       
   351 	// Write contact data to the database.
       
   352 	WriteContactItemL(aItem, EInsert);
       
   353 	}
       
   354 
       
   355 /**
       
   356 Updates the given contact item in the database.
       
   357 
       
   358 @param aItem The contact item to be updated
       
   359 */
       
   360 void CPplContactTable::UpdateL(const CContactItem& aItem)
       
   361 	{
       
   362 	// If contact is marked as deleted and access count is zero then delete the
       
   363 	// contact otherwise update it.
       
   364 	if (aItem.IsDeleted() && (aItem.AccessCount() == 0) )
       
   365 		{
       
   366 		//update access field in contact table
       
   367 		RSqlStatement updateStmnt;
       
   368 		CleanupClosePushL(updateStmnt);
       
   369 		updateStmnt.PrepareL(iDatabase, iAccessCountUpdateStmnt->SqlStringL() );
       
   370 		
       
   371 		const TInt KAccessCountParamIndex(KFirstParam);					// first parameter in query...
       
   372 		const TInt KContactIdParamIndex(KAccessCountParamIndex + 1);	// ...and the second.
       
   373 
       
   374 		User::LeaveIfError(updateStmnt.BindInt(KAccessCountParamIndex, 0) );
       
   375 		User::LeaveIfError(updateStmnt.BindInt(KContactIdParamIndex, aItem.Id()) );
       
   376 		User::LeaveIfError(updateStmnt.Exec() );
       
   377 		CleanupStack::PopAndDestroy(&updateStmnt);
       
   378 
       
   379 		TBool lowDiskErr(EFalse);
       
   380 		CContactItem* templ = DeleteLC(aItem.Id(), lowDiskErr);
       
   381 		CleanupStack::PopAndDestroy(templ);
       
   382 		if (lowDiskErr)
       
   383 			{
       
   384 			User::Leave(KErrDiskFull);
       
   385 			}
       
   386 		}
       
   387 	else
       
   388 		{
       
   389 		WriteContactItemL(aItem, EUpdate);
       
   390 		}
       
   391 	}
       
   392 
       
   393 /**
       
   394 Performs database write operations for the given contact item.
       
   395 
       
   396 @param aItem the contact item to be written
       
   397 @param aType the type of operation (insert or update) to 
       
   398 */
       
   399 void CPplContactTable::WriteContactItemL(const CContactItem& aItem, TCntSqlStatement aType)
       
   400 	{
       
   401 	// check the correct type of statement/operation has been supplied
       
   402 	if (aType != EInsert && aType != EUpdate)
       
   403 		{
       
   404 		User::Leave(KErrArgument);
       
   405 		}
       
   406 
       
   407 	// temporary reference to the CCntSqlStatements member variables to take advantage 
       
   408 	// of the commonality between update and insert operations.
       
   409 	CCntSqlStatement* tempCntStmnt = iUpdateStmnt;
       
   410 	if (aType == EInsert)
       
   411 		{
       
   412 		tempCntStmnt = iInsertStmnt;
       
   413 		}
       
   414 	
       
   415 	RSqlStatement stmnt;
       
   416 	CleanupClosePushL(stmnt);
       
   417  	stmnt.PrepareL(iDatabase, tempCntStmnt->SqlStringL() );
       
   418 
       
   419 	// get the identity-type fields and build the hint fields
       
   420 	THintField hint;
       
   421 	const RArray<TUid>* custFiltFields = NULL;
       
   422 
       
   423 	if (aItem.Type() != KUidContactTemplate)
       
   424 		{
       
   425 		custFiltFields = &iProperties.CustomFilterableFieldsL(); // doesn't take ownership
       
   426 		}
       
   427 
       
   428 	for (TInt fieldNum = aItem.CardFields().Count() - 1; fieldNum >= 0; --fieldNum) 
       
   429 		{
       
   430 		const CContactItemField& field = aItem.CardFields()[fieldNum];
       
   431 		const TInt nameFieldUid = CPplContactTable::NameFieldUid(field);
       
   432 
       
   433 		// check if field should be stored in the Identity table.
       
   434 		if (nameFieldUid != KErrNotFound)
       
   435 			{
       
   436 			TPtrC textToSet = field.TextStorage()->Text();
       
   437 			if(textToSet.Length() > 0)
       
   438 			    {
       
   439 			    const TInt KParamIndex(User::LeaveIfError(stmnt.ParameterIndex(iFieldMap.FindL(nameFieldUid) ) ) );
       
   440     			User::LeaveIfError(stmnt.BindText(KParamIndex, textToSet));
       
   441 			    }			}
       
   442 		else if (field.StorageType() == KStorageTypeText &&  // the field is textual
       
   443 				 field.TextStorage()->Text().Length() )      // ignore empty fields
       
   444 			{
       
   445 			// the field is not stored in contact table but potentially maps to a hint
       
   446 			hint.UpdateHintL(field, *custFiltFields);
       
   447 			}
       
   448 		}
       
   449 
       
   450 	
       
   451 	
       
   452 	// bind other values to statement
       
   453 	if(aType == EInsert) 
       
   454 		{
       
   455 		TInt typeFlags(GenerateTypeFlags(aItem.Type(), aItem.Attributes(), hint.iValue) );
       
   456 		User::LeaveIfError(stmnt.BindInt(
       
   457 				User::LeaveIfError(stmnt.ParameterIndex(KContactTypeFlagsParam() ) ), typeFlags) );
       
   458 		}
       
   459 	else
       
   460 		{
       
   461 		User::LeaveIfError(stmnt.BindInt(
       
   462 				User::LeaveIfError(stmnt.ParameterIndex(KContactTypeParam() ) ), TCntPersistenceUtility::ContactTypeUidToTypeFlags(aItem.Type()) >> EContactType_Shift ) );
       
   463 		
       
   464 		TInt attrHint = (aItem.Attributes() << EContactAttributes_Shift) & EContactAttributes_Mask;
       
   465 		attrHint |= hint.iValue & EContactHintFlags_Mask;
       
   466 		User::LeaveIfError(stmnt.BindInt(
       
   467 				User::LeaveIfError(stmnt.ParameterIndex(KAttributesAndHintParam() ) ), attrHint ) );		
       
   468 		}
       
   469 	User::LeaveIfError(stmnt.BindInt(
       
   470 		User::LeaveIfError(stmnt.ParameterIndex(KContactTemplateIdParam() ) ), aItem.TemplateRefId()) );
       
   471 	User::LeaveIfError(stmnt.BindInt(
       
   472 		User::LeaveIfError(stmnt.ParameterIndex(KContactAccessCountParam() ) ), aItem.AccessCount()) );
       
   473 	if (aType == EInsert)
       
   474 		{
       
   475 		User::LeaveIfError(stmnt.BindInt64(
       
   476 			User::LeaveIfError(stmnt.ParameterIndex(KContactCreationDateParam() ) ), aItem.LastModified().Int64() ) );
       
   477 		}
       
   478 	TTime time;
       
   479 	time.UniversalTime();	
       
   480 	User::LeaveIfError(stmnt.BindInt64(
       
   481 		User::LeaveIfError(stmnt.ParameterIndex(KContactLastModifiedParam() ) ), time.Int64() ) );
       
   482 	User::LeaveIfError(stmnt.BindText(
       
   483 		User::LeaveIfError(stmnt.ParameterIndex(KContactGuidStringParam() ) ), const_cast<CContactItem&>(aItem).Guid() ) );
       
   484 	User::LeaveIfError(stmnt.BindInt(
       
   485 		User::LeaveIfError(stmnt.ParameterIndex(KContactIdParam() ) ), aItem.Id() ) );
       
   486 
       
   487 	// build the clob/blob parts of the update statement
       
   488 	RSqlParamWriteStream textHeader;
       
   489 	User::LeaveIfError(textHeader.BindBinary(stmnt, 
       
   490 		User::LeaveIfError(stmnt.ParameterIndex(KContactTextFieldHeaderParam() ) ) ) );	
       
   491 	CEmbeddedStore* textEmbeddedStore = CEmbeddedStore::NewLC(textHeader);
       
   492 
       
   493 	RSqlParamWriteStream binHeader;
       
   494 	User::LeaveIfError(binHeader.BindBinary(stmnt, 
       
   495 		User::LeaveIfError(stmnt.ParameterIndex(KContactBinaryFieldHeaderParam() ) ) ) );	
       
   496 	CEmbeddedStore* binaryEmbeddedStore = CEmbeddedStore::NewLC(binHeader);
       
   497 	
       
   498 	RSqlParamWriteStream textFields;
       
   499 	User::LeaveIfError(textFields.BindText(stmnt, 
       
   500 		User::LeaveIfError(stmnt.ParameterIndex(KContactTextFieldsParam() ) ) ) );
       
   501 	CleanupClosePushL(textFields);
       
   502 	
       
   503 	RSqlParamWriteStream binFields;
       
   504 	User::LeaveIfError(binFields.BindBinary(stmnt, 
       
   505 		User::LeaveIfError(stmnt.ParameterIndex(KContactBinaryFieldsParam() ) ) ) );
       
   506 	CEmbeddedStore* binaryEmbeddedBlobStore=CEmbeddedStore::NewLC(binFields);
       
   507 	
       
   508 	const CContactTemplate* sysTemplate = NULL;
       
   509 	if (aItem.Type() != KUidContactTemplate && aItem.Type() != KUidContactGroup)
       
   510 		{
       
   511 		// System template is needed unless we are creating a template.
       
   512 		sysTemplate = &iProperties.SystemTemplateL();
       
   513 		}
       
   514 
       
   515 	TCntPersistenceUtility::WriteBlobL(*textEmbeddedStore, textFields, *binaryEmbeddedStore, *binaryEmbeddedBlobStore, aItem, sysTemplate);
       
   516 
       
   517 	textHeader.CommitL();
       
   518 	textFields.CommitL();
       
   519 	binHeader.CommitL();
       
   520 	binFields.CommitL();
       
   521 
       
   522 	// execute the statement
       
   523 	User::LeaveIfError(stmnt.Exec() );
       
   524 
       
   525 	textHeader.Close();
       
   526 	binHeader.Close();
       
   527 	textFields.Close();
       
   528 	binFields.Close();
       
   529 	
       
   530 	CleanupStack::PopAndDestroy(5, &stmnt); //binaryEmbeddedBlobStore, textFields, binaryEmbeddedStore, textEmbeddedStore, stmnt
       
   531 	}
       
   532 
       
   533 /**
       
   534 Gets the variables for the three contact item fields represented by the type flags database field.
       
   535 
       
   536 @param aTypeFlags the type flags field to be decoded
       
   537 @param aType the type variable to be got
       
   538 @param aAttributes the attribute variable to be got
       
   539 @param aHintFields the hint fields variable to be got
       
   540 */
       
   541 void CPplContactTable::GetTypeFlagFields(TInt aTypeFlags, TUid& aType, TUint& aAttributes, TUint& aHintFields)
       
   542 	{
       
   543 	aType 		=  TCntPersistenceUtility::TypeFlagsToContactTypeUid(aTypeFlags); 
       
   544 	aAttributes = (aTypeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; 
       
   545 	aHintFields = TCntPersistenceUtility::TypeFlagsToHint(aTypeFlags);
       
   546 	}
       
   547 
       
   548 /**
       
   549 Creates a TInt of type_flags for insertion into the database.
       
   550 
       
   551 @return A bitmap representing all three parameter values ready to be inserted 
       
   552 into the database as a type_flags column value.
       
   553 
       
   554 @param aType
       
   555 @param aAttributes
       
   556 @param aHintFields
       
   557 */
       
   558 TInt CPplContactTable::GenerateTypeFlags(TUid aType, TUint aAttributes, TUint aHintFields)
       
   559 	{
       
   560 	TInt tmpVal = TCntPersistenceUtility::ContactTypeUidToTypeFlags(aType);
       
   561 	tmpVal |= (aAttributes << EContactAttributes_Shift) & EContactAttributes_Mask;
       
   562 	tmpVal |= aHintFields & EContactHintFlags_Mask;
       
   563 	return tmpVal;
       
   564 	}
       
   565 
       
   566 void CPplContactTable::DeleteL(const CContactItem& aItem, TBool& aLowDiskErrorOccurred)
       
   567 	{
       
   568 	CContactItem* item = DeleteLC(aItem.Id(), aLowDiskErrorOccurred);
       
   569 	CleanupStack::PopAndDestroy(item);
       
   570 	}
       
   571 
       
   572 /**
       
   573 Delete a contact item from the contact table
       
   574 
       
   575 @param aItemId contact item id
       
   576 @param aLowDiskErrorOccurred outparameter; will be set to ETrue if an attempt to delete in
       
   577 		low disk condition occured
       
   578 */
       
   579 CContactItem* CPplContactTable::DeleteLC(TContactItemId  aItemId, TBool& aLowDiskErrorOccurred)
       
   580 	{
       
   581 	// You can't delete the system template, because you couldn't read any cards otherwise.
       
   582 	__ASSERT_ALWAYS(aItemId != KGoldenTemplateId, User::Leave(KErrNotSupported) );
       
   583 
       
   584 	// select the relevant bits from the contact table for the contact item 
       
   585 	// and put them in a new contact item
       
   586 	RSqlStatement selectStmnt;
       
   587 	CleanupClosePushL(selectStmnt);
       
   588 	selectStmnt.PrepareL(iDatabase, iDeleteSelectStmnt->SqlStringL() );
       
   589 	const TInt KContactIdParamIndex(KFirstIndex); // first and only parameter in the query	
       
   590 	User::LeaveIfError(selectStmnt.BindInt(KContactIdParamIndex, aItemId ) );
       
   591 
       
   592 	// execute query
       
   593 	TInt err(selectStmnt.Next() );
       
   594 	if (err != KSqlAtRow)
       
   595 		{
       
   596 		if (err == KSqlAtEnd)
       
   597 			{
       
   598 			User::Leave(KErrNotFound);
       
   599 			}
       
   600 		User::LeaveIfError(err);
       
   601 		}
       
   602 	
       
   603 	// Obtain the contact type and create a new contact item of this type.
       
   604 	TInt typeFlags = selectStmnt.ColumnInt(iDeleteSelectStmnt->ParameterIndex(KContactTypeFlags() ) ) ;
       
   605 	TInt accessCount =  selectStmnt.ColumnInt(iDeleteSelectStmnt->ParameterIndex(KContactAccessCount() ) ) ;
       
   606 	TContactItemId templateId = selectStmnt.ColumnInt(iDeleteSelectStmnt->ParameterIndex(KContactTemplateId() ) ) ;
       
   607 
       
   608 	CleanupStack::PopAndDestroy(&selectStmnt);
       
   609 
       
   610 	TUid type = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags);
       
   611 	CContactItem* item = CContactItem::NewLC(type);
       
   612 	item->SetId(aItemId);
       
   613 	item->SetAttributes((typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift); 
       
   614 	item->SetAccessCount(accessCount);
       
   615 	item->SetTemplateRefId(templateId);
       
   616 	
       
   617 	if (item->IsDeletable() )
       
   618 		{
       
   619 		// delete it here
       
   620 		RSqlStatement deleteStmnt;
       
   621 		CleanupClosePushL(deleteStmnt);
       
   622 		deleteStmnt.PrepareL(iDatabase, iDeleteStmnt->SqlStringL() );
       
   623 		User::LeaveIfError(deleteStmnt.BindInt(KContactIdParamIndex, aItemId) );
       
   624 		TInt err = deleteStmnt.Exec();
       
   625 		CleanupStack::PopAndDestroy(&deleteStmnt);
       
   626 
       
   627 		if (err == KErrDiskFull)
       
   628 			{
       
   629 			aLowDiskErrorOccurred = ETrue;
       
   630 			}
       
   631 		else
       
   632 			{
       
   633 			User::LeaveIfError(err);
       
   634 			}
       
   635 		}
       
   636 	else // Not deletable because of access count > 0.
       
   637 		{
       
   638 		if (!item->IsDeleted() )
       
   639 			{
       
   640 			// Set and persist the deleted flag.
       
   641 			item->SetDeleted(ETrue);
       
   642 
       
   643 			// update attributes in the contact table
       
   644 			typeFlags |= (item->Attributes()) << EContactAttributes_Shift;
       
   645 			RSqlStatement updateStmnt;
       
   646 			CleanupClosePushL(updateStmnt);
       
   647 			updateStmnt.PrepareL(iDatabase, iUpdateFlagsStmnt->SqlStringL() );
       
   648 			const TInt KTypeFlagsParamIndex(KFirstParam);				// first parameter in query...
       
   649 			const TInt KContactIdParamIndex(KTypeFlagsParamIndex + 1);	// ...and the second.
       
   650 			User::LeaveIfError(updateStmnt.BindInt(KTypeFlagsParamIndex, typeFlags) );
       
   651 			User::LeaveIfError(updateStmnt.BindInt(KContactIdParamIndex, item->Id()) );
       
   652 			User::LeaveIfError(updateStmnt.Exec() );
       
   653 			CleanupStack::PopAndDestroy(&updateStmnt);
       
   654 			}
       
   655 		}
       
   656 
       
   657 	if (!item->IsDeleted() && !aLowDiskErrorOccurred)
       
   658 		{
       
   659 		// Decrement Template reference counter.
       
   660 		UpdateTemplateAccessCounterL(item->TemplateRefId(), EFalse);
       
   661 		}
       
   662 
       
   663 	// Ownership is passed to the caller, who can do additional analysis of the item.
       
   664 	return item;
       
   665 	}
       
   666 
       
   667 
       
   668 /**
       
   669 Create the contact table in the database.
       
   670 */
       
   671 void CPplContactTable::CreateTableL()
       
   672 	{
       
   673 	User::LeaveIfError(iDatabase.Exec(KContactCreateStmnt) );
       
   674 	}
       
   675 
       
   676 
       
   677 /**
       
   678 Change the type of the given contact item to the given type.
       
   679 
       
   680 @param aItemId Contact item ID whose type is to be changed.
       
   681 @param aNewType New type for contact item.
       
   682 */
       
   683 void CPplContactTable::ChangeTypeL(TContactItemId aItemId, TUid aNewType)
       
   684 	{
       
   685    	if(aItemId == KNullContactId)
       
   686    	    {
       
   687    	    return;
       
   688    	    }
       
   689 	
       
   690 	// get the type flags for the contact item
       
   691 	const TInt bufSize(KSelectFlagsSqlStmntFormat().Size() + NumDigits(aItemId) );
       
   692 	HBufC* buf = HBufC::NewLC(bufSize);
       
   693 	TPtr selectTypeFlagsSqlStmnt(buf->Des() );
       
   694 	selectTypeFlagsSqlStmnt.AppendFormat(KSelectFlagsSqlStmntFormat, aItemId);
       
   695 	TSqlScalarFullSelectQuery selectTypeFlagsQuery(iDatabase);
       
   696 	TInt typeFlags = selectTypeFlagsQuery.SelectIntL(selectTypeFlagsSqlStmnt);
       
   697 	CleanupStack::PopAndDestroy(buf);
       
   698 
       
   699 	// deconstruct the type flags into the different fields and then rebuild it with the new type
       
   700 	TUid type;
       
   701 	TUint attributes;
       
   702 	TUint hintFields;
       
   703 	GetTypeFlagFields(typeFlags, type, attributes, hintFields);
       
   704 	typeFlags = GenerateTypeFlags(aNewType, attributes, hintFields); // use new type
       
   705 
       
   706 	// update type flags in the contact table
       
   707 	RSqlStatement updateStmnt;
       
   708 	CleanupClosePushL(updateStmnt);
       
   709 	updateStmnt.PrepareL(iDatabase, iUpdateFlagsStmnt->SqlStringL() );
       
   710 	User::LeaveIfError(updateStmnt.BindInt(updateStmnt.ParameterIndex(KContactTypeFlagsParam() ), typeFlags) );
       
   711 	User::LeaveIfError(updateStmnt.BindInt(updateStmnt.ParameterIndex(KContactIdParam()), aItemId) );
       
   712 	User::LeaveIfError(updateStmnt.Exec() );
       
   713 	CleanupStack::PopAndDestroy(&updateStmnt);
       
   714 	}
       
   715 
       
   716 /**
       
   717 CPplContactTable::THintField constructor.
       
   718 */
       
   719 CPplContactTable::THintField::THintField()
       
   720 	: iValue(0)
       
   721 	{
       
   722 	}
       
   723 
       
   724 
       
   725 /**
       
   726 CPplContactTable::THintField constructor.
       
   727 */
       
   728 CPplContactTable::THintField::THintField(TUint16 aExtHint, TUint8 aHint)
       
   729 	{
       
   730 	iValue = ((aExtHint << 8) | aHint);
       
   731 	}
       
   732 
       
   733 
       
   734 /** 
       
   735 Update the hint value using the given contact field and custom filterable
       
   736 fields.
       
   737 
       
   738 @param aField Contact field.
       
   739 @param aCustFiltFields Custom filterable fields.
       
   740 */
       
   741 void CPplContactTable::THintField::UpdateHintL(const CContactItemField& aField, const RArray<TUid>& aCustFiltFields)
       
   742 	{
       
   743 	const CContentType& type = aField.ContentType();
       
   744 
       
   745 	if (type.ContainsFieldType(KUidContactFieldVCardMapWORK) )
       
   746 		{
       
   747 		iValue |= CContactDatabase::EWork;
       
   748 		}
       
   749 
       
   750 	if (type.ContainsFieldType(KUidContactFieldVCardMapHOME) )
       
   751 		{
       
   752 		iValue |= CContactDatabase::EHome;
       
   753 		}
       
   754 
       
   755 	if (type.ContainsFieldType(KUidContactFieldPhoneNumber) )
       
   756 		{
       
   757 		iValue |= CContactDatabase::EPhonable;
       
   758 
       
   759 		if(type.ContainsFieldType(KUidContactFieldVCardMapCELL) )
       
   760 			{
       
   761 			iValue |= CContactDatabase::ESmsable;
       
   762 			}
       
   763 		else if(!type.ContainsFieldType(KUidContactFieldVCardMapPAGER) )
       
   764 			{
       
   765 			iValue |= CContactDatabase::ELandLine;
       
   766 			}
       
   767 		}
       
   768 
       
   769 	if (type.ContainsFieldType(KUidContactFieldRingTone) )
       
   770 		{
       
   771 		CContactFieldStorage* storage = aField.Storage();
       
   772 		if ( storage && storage->IsFull() )
       
   773 			{
       
   774 			iValue |= CContactDatabase::ERingTone;
       
   775 			}
       
   776 		}
       
   777 
       
   778 	if (type.ContainsFieldType( KUidContactsVoiceDialField ) )
       
   779 		{
       
   780 		CContactFieldStorage* storage = aField.Storage();
       
   781 		if (storage && storage->IsFull() )
       
   782 			{
       
   783 			iValue |= CContactDatabase::EVoiceDial;
       
   784 			}
       
   785 		}
       
   786 
       
   787 	if(type.ContainsFieldType(KUidContactFieldFax) )
       
   788 		{
       
   789 		iValue |= CContactDatabase::EFaxable;
       
   790 		iValue |= CContactDatabase::EPhonable;
       
   791 		}
       
   792 
       
   793 	if(type.ContainsFieldType(KUidContactFieldIMAddress) )
       
   794 		{
       
   795 		CContactFieldStorage* storage = aField.Storage();
       
   796 		if(storage && storage->IsFull() )
       
   797 			{
       
   798 			iValue |= CContactDatabase::EIMAddress;
       
   799 			if(type.ContainsFieldType(KUidContactFieldVCardMapWV) )
       
   800 				{
       
   801 				iValue |= CContactDatabase::EWirelessVillage;
       
   802 				}
       
   803 			}
       
   804 		}
       
   805 
       
   806 	if (type.ContainsFieldType(KUidContactFieldEMail) )
       
   807 		{
       
   808 		iValue |= CContactDatabase::EMailable;
       
   809 		}
       
   810 
       
   811 	// Now check if given field type maps to one of the given (licensee) custom
       
   812 	// filterable fields.
       
   813 	
       
   814 	TInt index(KErrNotFound);
       
   815 
       
   816 	const TInt KCount = aCustFiltFields.Count();
       
   817 	for (TInt i = 0; i < KCount; ++i)
       
   818 		{
       
   819 		if (type.ContainsFieldType(aCustFiltFields[i]) )
       
   820 			{
       
   821 			index = i;
       
   822 			break;
       
   823 			}
       
   824 		}
       
   825 
       
   826 	if (index != KErrNotFound)
       
   827 		{
       
   828 		switch (index)
       
   829 			{
       
   830 			case 0:
       
   831 				iValue |= CContactDatabase::ECustomFilter1;
       
   832 				break;
       
   833 			case 1:
       
   834 				iValue |= CContactDatabase::ECustomFilter2;
       
   835 				break;
       
   836 			case 2:
       
   837 				iValue |= CContactDatabase::ECustomFilter3;
       
   838 				break;
       
   839 			case 3:
       
   840 				iValue |= CContactDatabase::ECustomFilter4;
       
   841 				break;
       
   842 			default:
       
   843 				__ASSERT_DEBUG(EFalse, User::Leave(KErrNotSupported) );
       
   844 				break;
       
   845 			}
       
   846 		}
       
   847 	}
       
   848 
       
   849 
       
   850 /**
       
   851 Get the hint extension value (upper 8 bits).
       
   852 
       
   853 @return Hint extension value.
       
   854 */
       
   855 TUint16 CPplContactTable::THintField::ExtHint()
       
   856 	{
       
   857 	return static_cast<TUint16>((iValue >> 8) & KMaxTUint16);
       
   858 	}
       
   859 
       
   860 
       
   861 /**
       
   862 Get the non-extended hint value (lower 8 bits).
       
   863 
       
   864 @return Non-extended hint value.
       
   865 */
       
   866 TInt8 CPplContactTable::THintField::Hint()
       
   867 	{
       
   868 	return static_cast<TInt8>(iValue & KMaxTUint8);
       
   869 	}
       
   870 
       
   871 
       
   872 
       
   873 /**
       
   874 Return the Identity field uid for the given contact field.
       
   875 
       
   876 @param Contact field.
       
   877 
       
   878 @return Identity field index corresponding to the given contact field.
       
   879 */
       
   880 TInt CPplContactTable::NameFieldUid(const CContactItemField& nameField)
       
   881 	{
       
   882 	// For all the name fields stored in the Identity table...
       
   883 	for (TInt nameFieldNum = 0; nameFieldNum < sizeof(KFastAccessFieldUids) / sizeof(TInt); ++nameFieldNum)
       
   884 		{
       
   885 		if (nameField.ContentType().ContainsFieldType(TUid::Uid(KFastAccessFieldUids[nameFieldNum]) ) )
       
   886 			{
       
   887 			return KFastAccessFieldUids[nameFieldNum];
       
   888 			}
       
   889 		}
       
   890 	return KErrNotFound;
       
   891 	}
       
   892 
       
   893 /**
       
   894   Utility function to calculate the number of digits in an integer.
       
   895   If a negative number, counts the - sign as an extra digit.
       
   896   
       
   897   @param aNum an integer
       
   898   
       
   899   @return TUint the number of digits
       
   900 */
       
   901 TUint CPplContactTable::NumDigits(TInt aNum)
       
   902 	{
       
   903   	TInt numDig(1);
       
   904   	if (aNum < 0)
       
   905   		{
       
   906   		++numDig;
       
   907   		aNum = -aNum;
       
   908   		}
       
   909   	while( (aNum /= 10) > 0)
       
   910   		{
       
   911   		++numDig;
       
   912   		}
       
   913   	return numDig;
       
   914   	}
       
   915   	
       
   916 /**	
       
   917 Utility method used to check if contact table is empty or not
       
   918 
       
   919 @return ETrue is the contact table is empty and EFalse otherwise
       
   920 */
       
   921 TBool CPplContactTable::IsTableEmptyL()
       
   922 	{
       
   923 	TInt count = 0;
       
   924 
       
   925 	HBufC* selectString = HBufC::NewLC(KCountSelect().Length() + 
       
   926 						KSqlContactTableName().Length()); 
       
   927 	TPtr ptrSelectString = selectString->Des();
       
   928 	ptrSelectString.Format(KCountSelect, &KSqlContactTableName);
       
   929 
       
   930 	TSqlScalarFullSelectQuery scalarQuery(iDatabase);
       
   931 	
       
   932 	count = scalarQuery.SelectIntL(ptrSelectString);
       
   933 	CleanupStack::PopAndDestroy(selectString);
       
   934 
       
   935 	return (count == 0);	
       
   936 	}
       
   937 
       
   938 /**
       
   939 Utility method used to retrieve card template ids
       
   940 */
       
   941 CContactIdArray& CPplContactTable::CardTemplateIdsL()
       
   942 	{
       
   943 	iCardTemplateIds->Reset();
       
   944 	
       
   945 	HBufC* selectString = HBufC::NewLC(KTwoTypeField().Length() + KContactId().Length() + KContactTypeFlags().Length() + 
       
   946 						KSqlContactTableName().Length() + KContactTypeFlags().Length() + 3); 
       
   947 	TPtr ptrSelectString = selectString->Des();
       
   948 	ptrSelectString.Format(KTwoTypeField, &KContactId, &KContactTypeFlags, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_CardTemplate);
       
   949 	
       
   950 	RSqlStatement selectStmnt;
       
   951 	CleanupClosePushL(selectStmnt);
       
   952 	selectStmnt.PrepareL(iDatabase, ptrSelectString );
       
   953 	
       
   954 	const TInt KIdIndex = selectStmnt.ColumnIndex(KContactId);
       
   955 	const TInt KTypeFlagsIndex = selectStmnt.ColumnIndex(KContactTypeFlags);
       
   956 	
       
   957 	TInt err;
       
   958 	while((err = selectStmnt.Next()) == KSqlAtRow)
       
   959 		{
       
   960 		TInt typeFlags = selectStmnt.ColumnInt(KTypeFlagsIndex);
       
   961 		TInt attr = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; 
       
   962 		if((attr & EContactAttrsFlags_Deleted) == 0)
       
   963 		    {
       
   964 		    //Only add templates are not marked as deleted.
       
   965     		iCardTemplateIds->AddL(selectStmnt.ColumnInt(KIdIndex));	
       
   966 		    }
       
   967 		}
       
   968 	
       
   969 	if (err != KSqlAtEnd)
       
   970 		{
       
   971 		User::Leave(err);
       
   972 		}
       
   973 
       
   974 	CleanupStack::PopAndDestroy(2,selectString);
       
   975 	
       
   976 	return *iCardTemplateIds;
       
   977 	}
       
   978 
       
   979 /**
       
   980 Utility method used to retrieve own card id
       
   981 */
       
   982 TContactItemId CPplContactTable::OwnCardIdL()
       
   983 	{
       
   984 	TContactItemId ownCardId = 0;
       
   985 	
       
   986 	HBufC* selectString = HBufC::NewLC(KOneTypeField().Length() + KContactId().Length() + 
       
   987 						KSqlContactTableName().Length() + KContactTypeFlags().Length() + 3); 
       
   988 	TPtr ptrSelectString = selectString->Des();
       
   989 	ptrSelectString.Format(KOneTypeField, &KContactId, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_OwnCard);
       
   990 	
       
   991 	RSqlStatement selectStmnt;
       
   992 	CleanupClosePushL(selectStmnt);
       
   993 	selectStmnt.PrepareL(iDatabase, ptrSelectString );
       
   994 	
       
   995 	const TInt idIndex = selectStmnt.ColumnIndex(KContactId);
       
   996 	
       
   997 	TInt err;
       
   998 	if((err = selectStmnt.Next()) == KSqlAtRow)
       
   999 		{
       
  1000 		ownCardId = selectStmnt.ColumnInt(idIndex);	
       
  1001 		}
       
  1002 	else
       
  1003 		{
       
  1004 		User::LeaveIfError(err);
       
  1005 		ownCardId = KErrNotFound;		
       
  1006 		}
       
  1007 	
       
  1008 	CleanupStack::PopAndDestroy(2,selectString);
       
  1009 	
       
  1010 	return ownCardId;
       
  1011 	}
       
  1012 	
       
  1013 /**
       
  1014 Utility method used to set own card id
       
  1015 */	
       
  1016 void CPplContactTable::SetOwnCardIdL(TContactItemId aId)
       
  1017 	{
       
  1018 	TContactItemId oldOwnCardId = OwnCardIdL();
       
  1019 	
       
  1020 	if(oldOwnCardId != aId)
       
  1021 	    {
       
  1022 	    //Change old own card to be contact card.
       
  1023         ChangeTypeL(oldOwnCardId, KUidContactCard);	    
       
  1024         
       
  1025 	    //set given card as own card.
       
  1026     	ChangeTypeL(aId, KUidContactOwnCard);
       
  1027 	    }
       
  1028 	}