/**
Change the sorting order/text definition. It should be always called when 
there is not an iteration started in persistence layer.

@param aTextDef the new text definition to be used in the view session.
*/
void CCntPplViewSession::ChangeSortOrderL(const CContactTextDef& aTextDef)
	{
	//Cleanup the cached Prepare statement as the sort order will be changed
	Cancel();
    CleanupCachedPrepareStatement();
	
	//Copy the text definition
	CContactTextDef* textDef = CContactTextDef::NewLC();
	const TInt KTextDefCount = aTextDef.Count();
	for (TInt index = 0; index < KTextDefCount; ++index)
		{
		textDef->AppendL(TContactTextDefItem(aTextDef.At(index).iFieldType));
		}
	
	// Create select statement on contact table
	TCntSqlStatementType statementType(ESelect, KSqlContactTableName());
	CCntSqlStatement* sqlSmt = TSqlProvider::GetSqlStatementL(statementType);
	CleanupStack::PushL(sqlSmt);
	
	// Always select id, type flags.	
	sqlSmt->SetParamL(KContactId(), KSpace());
	sqlSmt->SetParamL(KContactTypeFlags(), KSpace());
	
	//Go through text definition to construct select statement.
	TBool isFastAccessOnly = ETrue;
	for(TInt ii = 0; ii < KTextDefCount; ++ii)
		{
		const TDesC& KColunmName = TCntPersistenceUtility::GetFastAccessColumnNameById(aTextDef.At(ii).iFieldType.iUid);
		if(KColunmName.Length() > 0) 
			{
			sqlSmt->SetParamL(KColunmName, KSpace());
			}
		else
			{
			isFastAccessOnly = EFalse;		
			}
		}
	
	if(!isFastAccessOnly)
		{
		//Fields in text blob are needed, add text fields header and
        //text blob columns in the select statement.		
		sqlSmt->SetParamL(KContactTextFieldHeader(), KSpace());
		sqlSmt->SetParamL(KContactTextFields(), KSpace());
		}

	CleanupStack::Pop(2, textDef); // sqlSmt, textDef.
	
	delete iCntSqlStatement;
	iCntSqlStatement = sqlSmt;
	
	delete iTextDef;
	iTextDef = textDef;
	
	iIsFastAccessFieldsOnly = isFastAccessOnly;
	}
/**
Utility method used to read binary blob fields from contacts database. Provides a mechanism to
fill a contact item with informations stored in binary blobs within contact database.
A reference to the contact item to be fill has to be provided. A template has to be provided
if the contact item is based on a template. Template can be NULL. Also a view definition can
be provided to filter which fields are read from blob fields.

@param		aItem Contact item to be filled with information from binary blob field.
@param		aView View definition specifying what item fields should be read from binary blob field
@param		aTemplate Contact item representing a template based on which aItem should be read. Can be NULL
@param		aDatabase RSqlDatabase reference.
@leave		KErrNotFound if the specified contact item does not exist any more in contact database
*/	
void TCntPersistenceUtility::ReadBinaryBlobL(CContactItem& aItem, const CContactItemViewDef& aView, const CContactItem* aTemplate, RSqlDatabase& aDatabase)
	{
	HBufC* selectString = HBufC::NewLC(KSelectTwoFields().Length() + KContactBinaryFieldHeader().Length() + KContactBinaryFields().Length() + KSqlContactTableName().Length() + KContactId().Length());
	TPtr ptrSelectString = selectString->Des();
	ptrSelectString.Format(KSelectTwoFields, &KContactBinaryFieldHeader, &KContactBinaryFields, &KSqlContactTableName, &KContactId, aItem.Id());
	
	RSqlStatement selectStmt;
	CleanupClosePushL(selectStmt);
	User::LeaveIfError(selectStmt.Prepare(aDatabase, ptrSelectString));

	TInt err = selectStmt.Next();
	if(err != KSqlAtRow)
		{
		if(err == KSqlAtEnd)
			{
			User::Leave(KErrNotFound);	
			}
		else
			{
			User::Leave(err);	
			}	
		}
	
	TPtrC8 binaryHeader;
	selectStmt.ColumnBinary(User::LeaveIfError(selectStmt.ColumnIndex(KContactBinaryFieldHeader)), binaryHeader);
	RDesReadStream binaryHeaderStream(binaryHeader);
	CleanupClosePushL(binaryHeaderStream);
	CEmbeddedStore* binaryHeaderStore = CEmbeddedStore::FromLC(binaryHeaderStream);
	
	TPtrC8 binaryFields;
	selectStmt.ColumnBinary(User::LeaveIfError(selectStmt.ColumnIndex(KContactBinaryFields)), binaryFields);
	RDesReadStream binaryFieldsStream(binaryFields);
	CleanupClosePushL(binaryFieldsStream);
	CEmbeddedStore* binaryBlobStore = CEmbeddedStore::FromLC(binaryFieldsStream);

	ReadBinaryBlobL(*binaryHeaderStore, *binaryBlobStore, aItem, aView, aTemplate);	

	CleanupStack::PopAndDestroy(6, selectString); //binaryHeaderStore, binaryHeaderStrean, binaryBlobStore, binaryBlobStream, selectStmt, selectString
	}
void CPredictiveSearchSynchronizer::CreatePredSearchTablesL(TBool aAllTables)
	{
	PRINT1(_L("CPredictiveSearchSynchronizer::CreatePredSearchTablesL all=%d"), aAllTables);

	if (aAllTables)
		{
		i12keyTable.CreateTableL();
		iSettingsTable.CreateTableL();
		iSettingsTable.StoreCurrentLanguageL();
		}
	iQwertyTable.CreateTableL();

	_LIT(KSelectAllContactsFormat, "SELECT %S,%S,%S FROM %S;");
	TInt bufSize = KSelectAllContactsFormat().Length() +
				   KContactId().Length() +
				   KContactFirstName().Length() +
				   KContactLastName().Length() +
				   KSqlContactTableName().Length();
	HBufC* sqlStatement = HBufC::NewLC(bufSize);
	sqlStatement->Des().AppendFormat(KSelectAllContactsFormat,
		&KContactId,
		&KContactFirstName,
		&KContactLastName,
		&KSqlContactTableName);

	RSqlStatement stmnt;
	CleanupClosePushL(stmnt);
	PRINT1(_L("CreatePredSearchTablesL prepare SQL statement:%S"), sqlStatement);
    stmnt.PrepareL(iDatabase, *sqlStatement);

	const TInt KContactIdIndex = 0;
	const TInt KFirstNameIndex = 1;
	const TInt KLastNameIndex = 2;
	TInt err(KErrNone);
    while ((err = stmnt.Next()) == KSqlAtRow)
        {
		PRINT(_L("CreatePredSearchTablesL create CContactItem"));

		TInt id = KUidContactCardValue;
		TUid uid;
		uid.iUid = id;
		CContactItem* contact = CContactItem::NewLC(uid);
		contact->SetId(stmnt.ColumnInt(KContactIdIndex));

		// If first name exists, write it to contact item
		TPtrC firstName;
		if (stmnt.ColumnText(KFirstNameIndex, firstName) == KErrNone)
			{
			CContactItemField* field =
				CContactItemField::NewLC(KStorageTypeText, KUidContactFieldGivenName);
			CContactTextField* textfield = field->TextStorage();
			textfield->SetTextL(firstName);
			contact->AddFieldL(*field); // Takes ownership
			CleanupStack::Pop(field);
			}

		TPtrC lastName;
		if (stmnt.ColumnText(KLastNameIndex, lastName) == KErrNone)
			{
			CContactItemField* field =
				CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);
			CContactTextField* textfield = field->TextStorage();
			textfield->SetTextL(lastName);
			contact->AddFieldL(*field); // Takes ownership
			CleanupStack::Pop(field);
			}
		PRINT(_L("CreatePredSearchTablesL create entry to tables"));
		if (aAllTables)
			{
			i12keyTable.CreateInDbL(*contact);
			}
		if (ReadMailAddressesL(*contact))
			{
			iQwertyTable.CreateInDbL(*contact);
			}

		CleanupStack::PopAndDestroy(contact);
        }

    // Leave if we didn't complete going through the results properly
    if (err != KSqlAtEnd)
        {
		PRINT1(_L("CreatePredSearchTablesL SQL err=%d"), err);
        User::Leave(err);
        }
    CleanupStack::PopAndDestroy(&stmnt);
	CleanupStack::PopAndDestroy(sqlStatement);

	PRINT(_L("CPredictiveSearchSynchronizer::CreatePredSearchTablesL ends"));
	}