/** 
Retrieve the field text for the given field type and contact item ID.

The behaviour differs when a specific field type is not given i.e. when
aFieldType is KUidContactFieldMatchAll:

- First tries to find an email for the given contact item ID.
- If there is no email then it retrieves the first entry in Fast Access fields
for the given contact item ID.
- If there is no Fast Access fields then it retrieves the first entry in the
text fields blob for the given contact item ID.

Text for all other field types are retrieved from the text fields blob.

The caller must determine that the given contact item ID exists before calling
this method.
*/
void CCntPplViewSession::TextFieldL(RSqlStatement& aSqlStatement, const CCntSqlStatement& aCntSqlStmt, const CContactTemplate& aSystemTemplate, TFieldType aFieldType, TDes& aText)
	{
	TPtrC8 textHeader;
	aSqlStatement.ColumnBinary(aCntSqlStmt.ParameterIndex(KContactTextFieldHeader()), textHeader);
	RDesReadStream textHeaderStream(textHeader);
	CleanupClosePushL(textHeaderStream);	
    CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
    
	RStoreReadStream textHeaderStoreStream;
   	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());

	TPtrC textFieldPtrC = aSqlStatement.ColumnTextL(aCntSqlStmt.ParameterIndex(KContactTextFields()));
	HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
	
	if(aFieldType == KUidContactFieldMatchAll)
		{
		if (TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText) == EFalse)
			{
			CContactDatabase::TTextFieldMinimal	fastAccessText;
			if (HasTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, fastAccessText))
				{
				aText.Copy(fastAccessText);		
				}
			}
		} 
	else
		{
		if (SpecificTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, aFieldType, aText) == EFalse)
			{
			TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText);
			}
		}
		
	CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
	}
/**
Performs write (Insert/Update) operations for indiviual communication addresses of
type "Email address" or "SIP Address".
*/
void CPplCommAddrTable::DoNonPhoneWriteOpL(const TDesC& aAddress, const TCntSqlStatement aType,
										 TInt aCntId, TCommAddrType aAddrType, TInt aCommAddrId)
	{
	// leave if the statement type is not insert or update.
	// also, we can't update if aCommAddrId is 0 as we don't know the record's id
	if ((aType != EUpdate && aType != EInsert) || (aType == EUpdate && aCommAddrId == 0) )
		{
		User::Leave(KErrNotFound);
		}

	RSqlStatement stmnt;
	CleanupClosePushL(stmnt);

	// temporary reference to the CCntSqlStatements member variables to take advantage
	// of the commonality between update and insert operations.
	CCntSqlStatement* tempCntStmnt = iUpdateStmnt;
	if (aType == EInsert)
		{
		tempCntStmnt = iInsertStmnt;
		}

	User::LeaveIfError(stmnt.Prepare(iDatabase, tempCntStmnt->SqlStringL() ) );
	User::LeaveIfError(stmnt.BindInt(tempCntStmnt->ParameterIndex(KCommAddrContactId() ), aCntId) );
	User::LeaveIfError(stmnt.BindText(tempCntStmnt->ParameterIndex(KCommAddrValue() ), aAddress) );
	User::LeaveIfError(stmnt.BindNull(tempCntStmnt->ParameterIndex(KCommAddrExtraValue() ) ) );
	User::LeaveIfError(stmnt.BindInt(tempCntStmnt->ParameterIndex(KCommAddrType() ), aAddrType) );

	if (aType == EInsert)
		{
		User::LeaveIfError(stmnt.BindNull(tempCntStmnt->ParameterIndex(KCommAddrId() ) ) );
		}
	else
		{
		// it's the sixth parameter in the query and is in the WHERE
		// clause so we can't get its index from the CCntSqlStatement
		const TInt KCommAddrIdParamIndex(KFirstIndex + 5);
		User::LeaveIfError(stmnt.BindInt(KCommAddrIdParamIndex, aCommAddrId) );
		}

	User::LeaveIfError(stmnt.Exec() );
	CleanupStack::PopAndDestroy(&stmnt);
	}
/**
Checks if the given field type is in the Fast Access fields and if so the field text
is returned via the parameter aText.

@param aCntItemId The contact ID for which the specific text field is required.
@param aText On return contains the field text for the first Fast Access fields
with field type aFieldType.
@param aFieldType The specific field requested.

@return ETrue if the specific fast access text field was found, EFalse otherwise.
*/
TBool CCntPplViewSession::SpecificTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, const TFieldType aFieldType, TDes& aText)
	{
    const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(aFieldType.iUid);
	if(KColumnName.Length() > 0)
		{
		// This is a fast access field.
		TPtrC fastAccessText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
		TCntPersistenceUtility::CopyMinFieldText(fastAccessText, aText);
		return ETrue;
		}
	return EFalse;
	}
/**
The first text field in the Fast Access fields is found and returned via the
parameter aText.

@param aCntItemId The contact ID for which the first text field is required.
@param aText On return contains the text for the field of the first Identity
text field.

@return ETrue if a Fast Access text field was found, EFalse otherwise.
*/
TBool CCntPplViewSession::HasTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, TDes& aText)
	{
	for(TInt ii = EGivenName; ii <= ECompanyNamePrn; ++ii)
		{
		const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(KFastAccessFieldUids[ii]);
		TPtrC identText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
		if(identText.Length() > 0)
			{
			TCntPersistenceUtility::CopyMinFieldText(identText, aText);
			return ETrue;
			}
		}
	return EFalse;
	}