diff -r 000000000000 -r c53acadfccc6 metadataengine/server/src/mdsfindsequence.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/metadataengine/server/src/mdsfindsequence.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,642 @@ +/* +* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Manages object search from database* +*/ + +#include + +#include "mdsfindsequence.h" + +#include "mdcitem.h" +#include "mdcresult.h" +#include "mdcserializationbuffer.h" +#include "mdsschema.h" +#include "mdslogger.h" +#include "mdsfindengine.h" +#include "mdssqlfindoperation.h" +#include "mdssqliteconnection.h" +#include "mdsfindsqlclause.h" +#include "mdsdbconnectionpool.h" +#include "mdsclausebuffer.h" + + +/** logging instance */ +__USES_LOGGER + + +// ------------------------------------------------ +// NewL +// ------------------------------------------------ +// +CMdSFindSequence* CMdSFindSequence::NewL( + CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver ) + { + CMdSFindSequence* self = CMdSFindSequence::NewLC( aServer, aSchema, aObserver ); + CleanupStack::Pop( self ); + return self; + } + +// ------------------------------------------------ +// NewLC +// ------------------------------------------------ +// +CMdSFindSequence* CMdSFindSequence::NewLC( + CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver ) + { + CMdSFindSequence* self = new(ELeave) CMdSFindSequence( aServer, aSchema, aObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ------------------------------------------------ +// Default constructor +// ------------------------------------------------ +// +CMdSFindSequence::CMdSFindSequence( + CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver ) + : CActive( CActive::EPriorityStandard ) + , iServer( aServer ) + , iSchema( aSchema ) + , iObserver( &aObserver ) + , iUserLevel( EUserLevelNone ) + { + iNotifyCount = KMaxTUint32; + + iFindOperation = NULL; + } + +// ------------------------------------------------ +// ConstructL +// ------------------------------------------------ +// +void CMdSFindSequence::ConstructL() + { + CActiveScheduler::Add( this ); + __INIT_LOGGER; + } + +// ------------------------------------------------ +// Destructor +// ------------------------------------------------ +// +CMdSFindSequence::~CMdSFindSequence() + { + CleanUp(); + + Cancel(); + } + +void CMdSFindSequence::SetFindParams( TUint32 aNotifyCount ) + { + iNotifyCount = aNotifyCount; + } + +// ------------------------------------------------ +// FindL +// ------------------------------------------------ +// +TInt CMdSFindSequence::FindL( + CMdCSerializationBuffer& aSerializedCriteria, + TUserLevel aUserLevel ) + { + __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) ); + + iUserLevel = aUserLevel; + + iSerializedCriteria = &aSerializedCriteria; + + if( iFindResults ) + { + delete iFindResults; + iFindResults = NULL; + } + + iFindOperation = CreateOperationL( aSerializedCriteria ); + + TInt result = KErrNone; + result = iFindOperation->ExecuteL(); + + iFindResults = iFindOperation->Results(); + + if( iFindResults ) + { + PostProcessL( *iFindResults ); + } + + return result; + } + +// ------------------------------------------------ +// ContinueL +// ------------------------------------------------ +// +TInt CMdSFindSequence::ContinueL() + { + __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) ); + + if( iFindResults ) + { + delete iFindResults; + iFindResults = NULL; + } + + TInt result = iFindOperation->ContinueL(); + + if ( result == KErrNone ) + { + iFindResults = iFindOperation->Results(); + + if( iFindResults ) + { + PostProcessL( *iFindResults ); + } + } + + return result; + } + +// ------------------------------------------------ +// FindAsync +// ------------------------------------------------ +// +void CMdSFindSequence::FindAsync(CMdCSerializationBuffer& aSerializedCriteria, + TUserLevel aUserLevel ) + { + __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) ); + + iUserLevel = aUserLevel; + + if( iFindResults ) + { + delete iFindResults; + iFindResults = NULL; + } + + iSerializedCriteria = &aSerializedCriteria; + + SetActive(); + TRequestStatus* pStatus = &iStatus; + User::RequestComplete( pStatus, EAsyncFind ); + } + +// ------------------------------------------------ +// ContinueAsync +// ------------------------------------------------ +// +void CMdSFindSequence::ContinueAsync() + { + __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) ); + + if( iFindResults ) + { + delete iFindResults; + iFindResults = NULL; + } + + SetActive(); + TRequestStatus* pStatus = &iStatus; + User::RequestComplete( pStatus, EContinueAsyncFind ); + } + +// ------------------------------------------------ +// Results +// ------------------------------------------------ +// +CMdCSerializationBuffer& CMdSFindSequence::ResultsL() const + { + if( !iFindResults ) + { + User::Leave( KErrCorrupt ); + } + + return *iFindResults; + } + +// ------------------------------------------------ +// SetResultMode +// ------------------------------------------------ +// +void CMdSFindSequence::SetResultMode( TBool aResultModeItems ) + { + iLastResultModeItems = aResultModeItems; + iObserver->SetResultMode( aResultModeItems ); + } + +// ------------------------------------------------ +// RunL +// ------------------------------------------------ +// +void CMdSFindSequence::RunL() + { + TInt result = 0; + + switch ( iStatus.Int() ) + { + case EAsyncFind: + { + iFindOperation = CreateOperationL( *iSerializedCriteria ); + result = iFindOperation->ExecuteL(); + break; + } + case EContinueAsyncFind: + { + if( iFindOperation ) + { + result = iFindOperation->ContinueL(); + } + else + { + result = KErrNotFound; + } + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFSRun") , KErrCorrupt ); +#endif + User::Leave( KErrCorrupt ); + } + } + if( result == KErrNone || result == KFindSetReady ) + { + iFindResults = iFindOperation->Results(); + + if( iFindResults ) + { + PostProcessL( *iFindResults ); + } + } + + if ( result == KFindSetReady ) + { + CMdSFindEngine* obs = iObserver; + if ( obs ) + { + obs->SetComplete( KErrNone ); + } + } + else if ( result == KErrCancel ) + { + CleanUp(); + // do NOT notify observer + } + else + { + CMdSFindEngine* obs = iObserver; + if ( obs ) + { + obs->FindComplete( result ); + } + } + } + +// ------------------------------------------------ +// RunError +// ------------------------------------------------ +// +TInt CMdSFindSequence::RunError( TInt aError ) + { + // Cleanup if RunL() leaves + CMdSFindEngine* obs = iObserver; + CleanUp(); + obs->FindComplete( aError ); + return KErrNone; + } + +// ------------------------------------------------ +// DoCancel +// ------------------------------------------------ +// +void CMdSFindSequence::DoCancel() + { + if ( !iFindOperation ) + { + // already finished + CleanUp(); + return; + } + TInt state = iFindOperation->State(); + if ( state == CMdSSqlFindOperation::EStateIdle ) + { + // loop is idle - safe to clean up. + CleanUp(); + } + else if ( state == CMdSSqlFindOperation::EStateRunning ) + { + // interrupt loop. + iFindOperation->Cancel(); + } + else if ( state == CMdSSqlFindOperation::EStateDead ) + { + // loop is already ending. + } + return; + } + +// ------------------------------------------------ +// CreateOperationL +// ------------------------------------------------ +// +CMdSSqlFindOperation* CMdSFindSequence::CreateOperationL( + CMdCSerializationBuffer& aSerializedCriteria ) + { + CMdSSqlFindOperation* operation = CreateOperationLC( aSerializedCriteria ); + CleanupStack::Pop( operation ); + return operation; + } + +// ------------------------------------------------ +// CreateOperationLC +// ------------------------------------------------ +// +CMdSSqlFindOperation* CMdSFindSequence::CreateOperationLC( + CMdCSerializationBuffer& aSerializedCriteria ) + { + CMdSSqlFindOperation* operation = CMdSSqlFindOperation::NewLC( *this, iNotifyCount ); + + CMdSFindSqlClause& findSqlClause = operation->FindCriteria(); + + if( aSerializedCriteria.Buffer().Ptr() && aSerializedCriteria.Buffer().Length() != 0 ) + { + findSqlClause.CreateL( aSerializedCriteria, iUserLevel ); + + operation->SetLimit( findSqlClause.Limit() ); + + __LOGQUERY_16( _L("Execute query:"), operation->FindCriteria().AsTextL(), operation->FindCriteria().Variables() ); + } + else + { + User::Leave( KErrBadDescriptor ); + } + + return operation; + } + +struct TObjectHitCount + { + TInt iCount; + TUint32 iObjectOffset; + }; + +static TInt SortValues(const TObjectHitCount& aFirst, const TObjectHitCount& aSecond) + { + TInt result = aSecond.iCount - aFirst.iCount; + if (result == 0) + { + result = aFirst.iObjectOffset - aSecond.iObjectOffset; + } + return result; + } + +void CMdSFindSequence::GetFreeTextForObjectL( CDesCArray& aResultWordBuffer, + TDefId aNamespaceDefId, TItemId aObjectId ) + { + _LIT( KMdSFindSeqWords, "SELECT Word FROM TextSearch%u AS ts, TextSearchDictionary%u AS tsd ON tsd.WordId = ts.WordId WHERE ObjectId = ? ORDER BY Position ASC;" ); + + CMdsClauseBuffer* buffer = CMdsClauseBuffer::NewLC( KMdSFindSeqWords.iTypeLength + 20 ); // two int + buffer->BufferL().Format( KMdSFindSeqWords, aNamespaceDefId, aNamespaceDefId ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RRowData data; + CleanupClosePushL( data ); + data.AppendL( TColumn( aObjectId ) ); + RMdsStatement query; + CleanupClosePushL( query ); + connection.ExecuteQueryL( buffer->ConstBufferL(), query, data ); + TPtrC16 word; + data.Column(0).Set( word ); + while (connection.NextRowL(query, data)) + { + data.Column(0).Get( word ); + aResultWordBuffer.AppendL( word ); + data.Free(); + } + + CleanupStack::PopAndDestroy( 3, buffer ); // query, data, buffer + } + +// ------------------------------------------------ +// PostProcessL +// ------------------------------------------------ +// +void CMdSFindSequence::PostProcessL( CMdCSerializationBuffer& aSerializedResultBuffer ) + { +#ifdef _DEBUG + _LIT( KFindFunctionName, "CMdSFindSequence::PostProcessL" ); +#endif + + // process only on items result + if (!iLastResultModeItems) + { + return; + } + + if(iFindOperation && iFindOperation->FindCriteria().IncludesFreetexts() == EFalse ) + { + return; + } + + if (!iFindOperation) + { + return; + } + + RPointerArray& searchFreeText = iFindOperation->QueryFreeText(); + // to through every object and check freetext + aSerializedResultBuffer.PositionL( KNoOffset ); + const TMdCItems& items = TMdCItems::GetFromBufferL( aSerializedResultBuffer ); + const TBool needToSort = searchFreeText.Count() != 0 + && items.iObjects.iPtr.iCount > 1; + + RArray hitCountArray; + CleanupClosePushL( hitCountArray ); + + TObjectHitCount hitCount; + for( TUint32 i = 0; i < items.iObjects.iPtr.iCount; ++i ) + { + aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset + + i * sizeof(TMdCObject) ); + const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer ); + // check all objects + + // jump to freetext + if ( object.iFreeTexts.iPtr.iCount == 0 ) + { + continue; + } + + CDesC16ArrayFlat* resultWordBuffer = new(ELeave) CDesC16ArrayFlat( object.iFreeTexts.iPtr.iCount ); + CleanupStack::PushL( resultWordBuffer ); + // get freetext for object + GetFreeTextForObjectL( *resultWordBuffer, items.iNamespaceDefId, object.iId ); + __ASSERT_DEBUG( object.iFreeTexts.iPtr.iCount == resultWordBuffer->Count(), User::Panic( KFindFunctionName, KErrCorrupt) ); + + if (needToSort) + { + hitCount.iObjectOffset = items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject); + hitCount.iCount = GetFreeTextHitCountL( *resultWordBuffer, searchFreeText ); + hitCountArray.AppendL( hitCount ); + } + + aSerializedResultBuffer.PositionL( object.iFreeTexts.iPtr.iOffset ); + for ( TUint32 f = 0; f < object.iFreeTexts.iPtr.iCount; ++f ) + { + // insert freeText here + TPtrC16 word = (*resultWordBuffer)[f]; + aSerializedResultBuffer.InsertL( word ); + } + CleanupStack::PopAndDestroy( resultWordBuffer ); + } + + if ( needToSort && hitCountArray.Count() > 1 ) + { + hitCountArray.Sort( TLinearOrder( SortValues ) ); + + RArray objectArray; + CleanupClosePushL( objectArray ); + objectArray.Reserve( items.iObjects.iPtr.iCount ); + // store objects in array in correct order + for( TInt i = 0; i < items.iObjects.iPtr.iCount; ++i ) + { + aSerializedResultBuffer.PositionL( hitCountArray[i].iObjectOffset ); + const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer ); + objectArray.AppendL( object ); + } + // set them back in serialized buffer + aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset ); + for (TInt i = 0; i < items.iObjects.iPtr.iCount; ++i) + { + objectArray[i].SerializeL( aSerializedResultBuffer ); + } + CleanupStack::PopAndDestroy( &objectArray ); + } + + CleanupStack::PopAndDestroy( &hitCountArray ); + } + +// ------------------------------------------------ +// CleanUp +// ------------------------------------------------ +// +void CMdSFindSequence::CleanUp() + { + // clean up rubbish + if( iFindOperation ) + { + delete iFindOperation; + iFindOperation = NULL; + } + + iObserver = NULL; + + if( iFindResults ) + { + delete iFindResults; + iFindResults = NULL; + } + } + +// ------------------------------------------------ +// IsCleaned +// ------------------------------------------------ +// +TBool CMdSFindSequence::IsComplete() const + { + // not failed or query still running + if( //iObserver || + ( iFindOperation && iFindOperation->State() != CMdSSqlFindOperation::EStateDead ) ) + { + return EFalse; + } + + return ETrue; + } + +// ------------------------------------------------ +// IsComplete +// ------------------------------------------------ +// +TBool CMdSFindSequence::IsQueryComplete() const + { + if ( iFindOperation ) + { + return ( iFindOperation->State() == CMdSSqlFindOperation::EStateDead ); + } + else + { + return ETrue; + } + } + +const CMdsSchema& CMdSFindSequence::Schema() const + { + return iSchema; + } + +CMdSServer& CMdSFindSequence::Server() const + { + return iServer; + } + +// ------------------------------------------------ +// GetFreeTextHitCountL +// ------------------------------------------------ +// +TUint32 CMdSFindSequence::GetFreeTextHitCountL( + const CDesCArray& aObjectFreeText, + const RPointerArray& aSearchFreeText) + { + TUint32 hitCount = 0; + + const TInt objectFreeTextCount = aObjectFreeText.Count(); + + for(TInt i = 0; i < objectFreeTextCount; ++i) + { + TInt length = aObjectFreeText[i].Length(); + const TDesC& objectText = aObjectFreeText[i]; + const TInt32 objectTextLength = objectText.Length(); + const TInt searchFreeTextCount = aSearchFreeText.Count(); + + for( TInt j = 0; j < searchFreeTextCount; ++j ) + { + const TDesC& searchText = *aSearchFreeText[j]; + const TInt32 searchTextLength = searchText.Length(); + + if (searchTextLength > objectTextLength) + { + continue; + } + TInt32 searchStart = 0; + while(objectTextLength - searchStart >= searchTextLength) + { + const TInt retValue = objectText.Mid(searchStart, + objectTextLength - searchStart).FindF(searchText); + + if(retValue != KErrNotFound) + { + searchStart += retValue+searchTextLength; + hitCount++; + } + else + { + break; + } + } + } + } + return hitCount; + }