diff -r 000000000000 -r c53acadfccc6 metadataengine/server/src/mdssqlfindoperation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/metadataengine/server/src/mdssqlfindoperation.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,1422 @@ +/* +* 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 using SQL,* +*/ + +#include "mdssqlfindoperation.h" + +#include "mdcresult.h" +#include "mdcitem.h" +#include "mdcserializationbuffer.h" +#include "mdsfindsequence.h" +#include "mdsobjectdef.h" +#include "mdsnamespacedef.h" +#include "mdspropertydef.h" +#include "mdsfindsqlclause.h" +#include "mdsserver.h" +#include "mdsdbconnectionpool.h" +#include "mdeinternalerror.h" + +const TInt KMaxResultSize = 1024*256; // 256 KiB + +CMdSSqlFindOperation* CMdSSqlFindOperation::NewL( + CMdSFindSequence& aFind, + TUint aSetSize + ) + { + CMdSSqlFindOperation* that = CMdSSqlFindOperation::NewLC( + aFind, aSetSize ); + CleanupStack::Pop( that ); + return that; + } + +CMdSSqlFindOperation* CMdSSqlFindOperation::NewLC( + CMdSFindSequence& aFind, + TUint aSetSize + ) + { + CMdSSqlFindOperation* that = new (ELeave) CMdSSqlFindOperation( + aFind, + aSetSize + ); + CleanupStack::PushL( that ); + that->ConstructL(); + return that; + } + +CMdSSqlFindOperation::CMdSSqlFindOperation( + CMdSFindSequence& aFind, + TUint aSetSize + ) + : iResultMode( EQueryResultModeFirst ), iResultRow(NULL), + iResultRows(), iResultCount( 0 ), iResults( NULL ), iFind ( aFind ), + iState( EStateIdle ), iSetSize( aSetSize ), iLimit( 0 ), + iLimitCounter( 0 ), iMemoryLimit( 0 ), + iHarvestingPrioritizationCount( 0 ) + { + } + +void CMdSSqlFindOperation::ConstructL() + { + iFindClause = CMdSFindSqlClause::NewL( const_cast(iFind.Schema()) ); + } + + +CMdSSqlFindOperation::~CMdSSqlFindOperation() + { + ConsumeRows(); + iResultRows.Close(); + + iResultIds.Close(); + + // doesn't own result row + iResultRow = NULL; + + iQueryId.Close(); + + delete iResults; + delete iFindClause; + } + +TInt CMdSSqlFindOperation::ExecuteL() + { + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + iResultRow = &iFindClause->ResultRow(); + iQueryType = iFindClause->QueryType(); + iResultMode = iFindClause->ResultMode(); + + if( EQueryResultModeFirst >= iResultMode || EQueryResultModeLast <= iResultMode ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOExe") , KErrMdEUnknownQueryResultMode ); +#endif + + User::Leave( KErrMdEUnknownQueryResultMode ); + } + + iFind.SetResultMode( iQueryType == EQueryTypeObject && iResultMode == EQueryResultModeItem ); + + connection.ExecuteQueryL( iFindClause->AsTextL(), iQueryId, iFindClause->Variables() ); + + iState = EStateRunning; + + iSetCounter = 0; + iMemoryLimit = 0; + iHarvestingPrioritizationCount = 0; + + return FetchResultsL(); + } + +TInt CMdSSqlFindOperation::ContinueL() + { + // Continue query: fetch next row + iSetCounter = 0; + iState = EStateRunning; + + return FetchResultsL(); + } + +TInt CMdSSqlFindOperation::FetchResultsL() + { + iMemoryLimit += EstimateBaseResultSize(); + + if( !iResultRow ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOFe1") , KErrCorrupt ); +#endif + + User::Leave( KErrCorrupt ); + } + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + while( ETrue ) + { + RRowData* resultRow = new (ELeave) RRowData(); + CleanupStack::PushL( resultRow ); + CleanupClosePushL( *resultRow ); + + resultRow->AppendColumnTypesL( *iResultRow ); + + // fetch next DB row + if ( !connection.NextRowL( iQueryId, *resultRow ) ) + { + CleanupStack::PopAndDestroy( 2, resultRow ); // close and delete resultRow separately + resultRow = NULL; + + TRAPD( err, AddToContainerL() ); + + if( KErrNone != err ) + { + iResults = NULL; + ConsumeRows(); + } + + connection.Terminate( iQueryId ); + iState = EStateDead; + return KErrNone; + } + + iMemoryLimit += EstimateResultRowSizeL( *resultRow ); + + // Check if maximum memory limit is reached or + // set/limit counter is more than maximum set/limit size. + if( KMaxResultSize <= iMemoryLimit ) + { + // Store all previus items to result buffer. + + TRAPD( err, AddToContainerL() ); + + if( KErrNone != err ) + { + iResults = NULL; + ConsumeRows(); + } + + // add estimated size to next result set + iMemoryLimit = EstimateResultRowSizeL( *resultRow ); + + if( EQueryResultModeItem == iResultMode || EQueryResultModeDistinctValues == iResultMode ) + { + // add result row to result rows pointer array + iResultRows.AppendL( resultRow ); + + iSetCounter++; + + // pop result row from cleanup stack twice + CleanupStack::Pop( 2, resultRow ); + } + else + { + if( EQueryResultModeId == iResultMode ) + { + TItemId itemId = 0; + resultRow->Column( 0 ).Get( itemId ); + iResultIds.AppendL( itemId ); + + iSetCounter++; + } + else + { + TUint32 count; + resultRow->Column( 0 ).Get( count ); + iResultCount += count; + } + + // pop and destroy result row from cleanup stack twice + CleanupStack::PopAndDestroy( 2, resultRow ); + } + + + resultRow = NULL; + + ++iLimitCounter; + + iState = EStateIdle; + connection.EnableTransaction( EFalse, iQueryId ); + return KFindSetReady; + } + else + { + if( EQueryResultModeItem == iResultMode || EQueryResultModeDistinctValues == iResultMode ) + { + // add result row to result rows pointer array + iResultRows.AppendL( resultRow ); + + iSetCounter++; + + // pop result row from cleanup stack twice + CleanupStack::Pop( 2, resultRow ); + } + else + { + if( EQueryResultModeId == iResultMode ) + { + TItemId itemId = 0; + resultRow->Column( 0 ).Get( itemId ); + iResultIds.AppendL( itemId ); + + iSetCounter++; + } + else + { + TUint32 count; + resultRow->Column( 0 ).Get( count ); + iResultCount += count; + } + + // pop and destroy result row from cleanup stack twice + CleanupStack::PopAndDestroy( 2, resultRow ); + } + + resultRow = NULL; + + ++iLimitCounter; + } + + // check for different exit conditions + if ( iState == EStateRunning ) + { + if ( iLimitCounter >= iLimit ) + { + TRAPD( err, AddToContainerL() ); + + if( KErrNone != err ) + { + iResults = NULL; + ConsumeRows(); + } + + connection.Terminate( iQueryId ); + iState = EStateDead; + return KErrNone; + } + else if( iSetCounter >= iSetSize ) + { + TRAPD( err, AddToContainerL() ); + + if( KErrNone != err ) + { + iResults = NULL; + ConsumeRows(); + } + + iState = EStateIdle; + connection.EnableTransaction( EFalse, iQueryId ); + return KFindSetReady; + } + } + else if ( iState == EStateStop ) + { + // stop instructed + connection.Terminate( iQueryId ); + iState = EStateDead; + return KErrCancel; + } + else + { +#ifdef _DEBUG + User::Panic( _L("MdSFOFe2") , KErrCorrupt ); +#endif + User::Leave( KErrCorrupt ); + } + } + } + +TInt CMdSSqlFindOperation::EstimateBaseResultSize() + { + switch( iResultMode ) + { + case EQueryResultModeItem: + return sizeof(TMdCItems); + + case EQueryResultModeId: + return sizeof(TMdCItemIds); + + case EQueryResultModeCount: + return sizeof(TMdCItemCounts); + + case EQueryResultModeDistinctValues: + return sizeof(TMdCItemIds); + + // should never happen + default: +#ifdef _DEBUG + User::Panic( _L( "MdSFOEBS" ), KErrMdEUnknownQueryResultMode ); +#endif + return 0; + } + } + +TInt CMdSSqlFindOperation::EstimateResultRowSizeL( RRowData& aRow ) + { + if( iResultMode == EQueryResultModeId ) + { + return CMdCSerializationBuffer::KRequiredSizeForTItemId; + } + else if( iResultMode == EQueryResultModeCount ) + { + return 0; + } + else if( iResultMode == EQueryResultModeDistinctValues ) + { + if( iFindClause->PropertyFilters().Count() != 1 ) + { + User::Leave( KErrCorrupt ); + } + + const RPointerArray& propertyFilters = iFindClause->PropertyFilters(); + + TInt rowSize = 0; + if( propertyFilters[0]->GetType() == EPropertyText ) + { + if ( !aRow.Column( 0 ).IsNull() ) + { + // Required size for text property + TPtrC16 value = TPtr16((TUint16*)0, 0); + aRow.Column( 0 ).Get( value ); + rowSize += CMdCSerializationBuffer::RequiredSize( value ); + } + } + else + { +#ifdef _DEBUG + User::Panic( _L("MdSFOEs1") , KErrMdEUnknownPropertyType ); +#endif + User::Leave( KErrMdEUnknownPropertyType ); + } + + return rowSize; + } + + switch( iQueryType ) + { + case EQueryTypeObject: + { + TInt rowSize = sizeof(TMdCObject); + + const TInt KUriColumn = 7; + + TPtrC16 uri = TPtr16((TUint16*)0, 0); + + // Required size for object URI + if (!aRow.Column( KUriColumn ).IsNull()) + { + aRow.Column( KUriColumn ).Get( uri ); + rowSize += CMdCSerializationBuffer::RequiredSize( uri ); + } + + if( iFindClause->NoObjectLocking() && iFindClause->ObjectDef() && iFindClause->ObjectDef()->GetId() != KBaseObjectDefId ) + { + // check if object is placeholder and add it to count of harvester + // prioritization URIs + const TInt KFlagsColumn = 2; + TUint32 flags = 0; + aRow.Column( KFlagsColumn ).Get( flags ); + if( flags & EMdEObjectFlagPlaceholder ) + { + if( iFind.Server().ReserveSpaceHarvestingPrioritizationUri( uri ) ) + { + iHarvestingPrioritizationCount++; + } + } + } + + // Required size for properties + CMdsObjectDef* objectDef = iFindClause->ObjectDef(); + + if( !objectDef ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOEs2") , KErrMdEUnknownObjectDef ); +#endif + User::Leave( KErrMdEUnknownObjectDef ); + } + + const RPointerArray& propertyFilters = iFindClause->PropertyFilters(); + + // no property filterss + if( propertyFilters.Count() <= 0 ) + { + const TInt count = objectDef->GetAllPropertiesCount(); + + // space for every property, even if it's "null" + rowSize += count * sizeof(TMdCProperty); + + for( TInt i = 0; i < count; i++ ) + { + const CMdsObjectDef::TMdsColumnOrder& propertyColumn = + objectDef->GetPropertyColumnL( i ); + + TColumn& column = aRow.Column( propertyColumn.iColumnId ); + + if( column.IsNull() ) + { + continue; + } + + if( propertyColumn.iPropertyDef.GetType() == EPropertyText ) + { + // Required size for text in text property + TPtrC16 value = TPtr16((TUint16*)0, 0); + column.Get( value ); + rowSize += CMdCSerializationBuffer::RequiredSize( value ); + } + } + } + // property filters + else + { + const TInt count = propertyFilters.Count(); + + // space for every property, even if it's "null" + rowSize += count * sizeof(TMdCProperty); + + for( TInt i = 0; i < count; i++ ) + { + CMdsPropertyDef* propDef = propertyFilters[i]; + + if( !propDef ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOEs3") , KErrMdEUnknownPropertyDef ); +#endif + User::Leave( KErrMdEUnknownPropertyDef ); + } + + TColumn& column = aRow.Column( KBaseObjectBasicValueColumnOffset + i ); + + if( column.IsNull() ) + { + continue; + } + + if( propDef->GetType() == EPropertyText ) + { + // Required size for text in text property + TPtrC16 value = TPtr16((TUint16*)0, 0); + column.Get( value ); + rowSize += CMdCSerializationBuffer::RequiredSize( value ); + } + } + } + + if( FindCriteria().IncludesFreetexts() ) + { + // In result row the second lastest column is free text count + const TInt freeTextCountColumn = aRow.Size() - 2; + + // Get free text count + TUint32 freeTextCount = 0; + aRow.Column( freeTextCountColumn ).Get( freeTextCount ); + + if( freeTextCount > 0 ) + { + // In result row last column is total free text length + const TInt totalFreeTextsLengthColumn = aRow.Size() - 1; + + // Get total free text length. + TUint32 totalFreeTextsLength = 0; + aRow.Column( totalFreeTextsLengthColumn ).Get( totalFreeTextsLength ); + + // Required size for free texts. + // For every free text length (TUint16) + rowSize += freeTextCount * ( CMdCSerializationBuffer::KRequiredSizeForEmptyText ); + // and total free text length * TUint16 + rowSize += totalFreeTextsLength * sizeof( TUint16 ); + } + } + + return rowSize; + } + + case EQueryTypeRelation: + return sizeof(TMdCRelation); + + case EQueryTypeEvent: + { + TInt rowSize = sizeof(TMdCEvent); + + // Required size for source and participant texts + TPtrC16 source = TPtr16((TUint16*)0, 0); + aRow.Column( 4 ).Get( source ); + rowSize += CMdCSerializationBuffer::RequiredSize( source ); + + TPtrC16 participant = TPtr16((TUint16*)0, 0); + aRow.Column( 5 ).Get( participant ); + rowSize += CMdCSerializationBuffer::RequiredSize( participant ); + + return rowSize; + } + + default: +#ifdef _DEBUG + User::Panic( _L( "MdSFOEs4" ), KErrMdEUnknownQueryResultMode ); +#endif + return 0; + } + } + +TInt CMdSSqlFindOperation::State() + { + return iState; + } + +void CMdSSqlFindOperation::Cancel() + { + if ( iState == EStateRunning ) + { + iState = EStateStop; + } + } + +RPointerArray& CMdSSqlFindOperation::QueryFreeText() + { + return iFindClause->QueryFreeText(); + } + + +CMdSFindSqlClause& CMdSSqlFindOperation::FindCriteria() + { + return *iFindClause; + } + +CMdCSerializationBuffer* CMdSSqlFindOperation::Results() + { + CMdCSerializationBuffer* results = iResults; + iResults = NULL; + return results; + } + +void CMdSSqlFindOperation::SetLimit(TUint32 aLimit) + { + iLimit = aLimit; + } + +void CMdSSqlFindOperation::SetOffset(TUint32 aOffset) + { + iOffset = aOffset; + } + +TMdCOffset CMdSSqlFindOperation::AddItemToContainerL( RRowData &aRow, TMdCOffset aFreespaceOffset ) + { + switch( iQueryType ) + { + case EQueryTypeObject: + { + aFreespaceOffset = AddObjectToContainerL( aRow, aFreespaceOffset ); + break; + } + case EQueryTypeEvent: + { + TMdCEvent event; + TPtrC16 source = TPtr16( ( TUint16* )0, 0 ); //KNullPtr16; + TPtrC16 participant = TPtr16( ( TUint16* )0, 0 ); //KNullPtr16; + + aRow.Column( 0 ).Get( event.iId ); + aRow.Column( 1 ).Get( event.iObjectId ); + aRow.Column( 2 ).Get( event.iDefId ); + aRow.Column( 3 ).Get( event.iTime ); + aRow.Column( 4 ).Get( source ); + aRow.Column( 5 ).Get( participant ); + + const TMdCOffset eventOffset = iResults->Position(); + + if ( source.Length() > 0 ) + { + event.iSourceText.iPtr.iCount = source.Length(); + event.iSourceText.iPtr.iOffset = aFreespaceOffset; + iResults->PositionL( aFreespaceOffset ); + aFreespaceOffset = iResults->InsertL( source ); + } + else + { + event.iSourceText.iPtr.iCount = 0; + event.iSourceText.iPtr.iOffset = KNoOffset; + } + + if ( participant.Length() > 0 ) + { + event.iParticipantText.iPtr.iCount = participant.Length(); + event.iParticipantText.iPtr.iOffset = aFreespaceOffset; + iResults->PositionL( aFreespaceOffset ); + aFreespaceOffset = iResults->InsertL( participant ); + } + else + { + event.iParticipantText.iPtr.iCount = 0; + event.iParticipantText.iPtr.iOffset = KNoOffset; + } + + iResults->PositionL( eventOffset ); + event.SerializeL( *iResults ); + break; + } + case EQueryTypeRelation: + { + TMdCRelation relation; + TUint32 flags ( 0 ); + + aRow.Column( 0 ).Get( relation.iId ); + aRow.Column( 1 ).Get( flags ); + aRow.Column( 2 ).Get( relation.iDefId ); + aRow.Column( 3 ).Get( relation.iLeftObjectId ); + aRow.Column( 4 ).Get( relation.iRightObjectId ); + aRow.Column( 5 ).Get( relation.iParameter ); + aRow.Column( 6 ).Get( relation.iGuidHigh ); + aRow.Column( 7 ).Get( relation.iGuidLow ); + aRow.Column( 8 ).Get( relation.iLastModifiedDate ); + + relation.SerializeL( *iResults ); + break; + } + // Unknown query type + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOAd1") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + return aFreespaceOffset; + } + +void CMdSSqlFindOperation::AddIdToContainerL( TItemId aId ) + { + switch( iQueryType ) + { + case EQueryTypeObject: + case EQueryTypeEvent: + case EQueryTypeRelation: + { + iResults->InsertL( aId ); + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOAd2") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + } + +void CMdSSqlFindOperation::CreateItemL() + { + TMdCItems items; + items.iNamespaceDefId = iFindClause->NamespaceDef()->GetId(); + items.iObjects.iPtr.iCount = 0; + items.iObjects.iPtr.iOffset = KNoOffset; + items.iRelations.iPtr.iCount = 0; + items.iRelations.iPtr.iOffset = KNoOffset; + items.iEvents.iPtr.iCount = 0; + items.iEvents.iPtr.iOffset = KNoOffset; + + // move after main header + iResults->PositionL( sizeof(TMdCItems) ); + + TUint32 count = iResultRows.Count(); + TMdCOffset freetextOffset = KNoOffset; + switch( iQueryType ) + { + case EQueryTypeObject: + { + // add objects header + items.iObjects.iPtr.iCount = count; + items.iObjects.iPtr.iOffset = iResults->Position(); + freetextOffset = items.iObjects.iPtr.iOffset + count * sizeof(TMdCObject); + + // initializate server's harvesting prioritization buffer + if( iHarvestingPrioritizationCount > 0 ) + { + iFind.Server().StartAddingHarvestingPrioritizationUrisL(); + } + + break; + } + case EQueryTypeEvent: + { + // add objects header + items.iEvents.iPtr.iCount = count; + items.iEvents.iPtr.iOffset = iResults->Position(); + freetextOffset = items.iEvents.iPtr.iOffset + count * sizeof(TMdCEvent); + break; + } + case EQueryTypeRelation: + { + // add objects header + items.iRelations.iPtr.iCount = count; + items.iRelations.iPtr.iOffset = iResults->Position(); + freetextOffset = items.iRelations.iPtr.iOffset + count * sizeof(TMdCRelation); + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOCr1") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + + iResults->PositionL( KNoOffset ); + items.SerializeL( *iResults ); + + //Set offset to objects/events/relations + for( TInt i = 0; i < count; i++ ) + { + switch ( iQueryType ) + { + case EQueryTypeObject: + { + iResults->PositionL( items.iObjects.iPtr.iOffset + + i * sizeof(TMdCObject) ); + freetextOffset = AddItemToContainerL( *iResultRows[i], freetextOffset ); + break; + } + case EQueryTypeEvent: + { + iResults->PositionL( items.iEvents.iPtr.iOffset + + i * sizeof(TMdCEvent) ); + freetextOffset = AddItemToContainerL( *iResultRows[i], freetextOffset ); + break; + } + case EQueryTypeRelation: + { + iResults->PositionL( items.iRelations.iPtr.iOffset + + i * sizeof(TMdCRelation) ); + freetextOffset = AddItemToContainerL( *iResultRows[i], freetextOffset ); + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOCr2") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + } + } + +void CMdSSqlFindOperation::CreateCountL() + { + TMdCItemCounts itemCounts; + itemCounts.iNamespaceDefId = iFindClause->NamespaceDef()->GetId(); + itemCounts.iObjects = 0; + itemCounts.iEvents = 0; + itemCounts.iRelations = 0; + + switch( iQueryType ) + { + case EQueryTypeObject: + { + itemCounts.iObjects = iResultCount; + break; + } + case EQueryTypeEvent: + { + itemCounts.iEvents = iResultCount; + break; + } + case EQueryTypeRelation: + { + itemCounts.iRelations = iResultCount; + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOCr3") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + + itemCounts.SerializeL( *iResults ); + } + +void CMdSSqlFindOperation::CreateIdL() + { + TMdCItemIds itemIds; + itemIds.iNamespaceDefId = iFindClause->NamespaceDef()->GetId(); + itemIds.iErrorCode = KErrNone; + itemIds.iObjectIds.iPtr.iCount = 0; + itemIds.iObjectIds.iPtr.iOffset = KNoOffset; + itemIds.iObjectUris.iPtr.iCount = 0; + itemIds.iObjectUris.iPtr.iOffset = KNoOffset; + itemIds.iEventIds.iPtr.iCount = 0; + itemIds.iEventIds.iPtr.iOffset = KNoOffset; + itemIds.iRelationIds.iPtr.iCount = 0; + itemIds.iRelationIds.iPtr.iOffset = KNoOffset; + + iResults->PositionL( sizeof(TMdCItemIds) ); + + TUint32 count = iResultIds.Count(); + switch( iQueryType ) + { + case EQueryTypeObject: + { + itemIds.iObjectIds.iPtr.iCount = count; + itemIds.iObjectIds.iPtr.iOffset = iResults->Position(); + break; + } + case EQueryTypeEvent: + { + itemIds.iEventIds.iPtr.iCount = count; + itemIds.iEventIds.iPtr.iOffset = iResults->Position(); + break; + } + case EQueryTypeRelation: + { + itemIds.iRelationIds.iPtr.iCount = count; + itemIds.iRelationIds.iPtr.iOffset = iResults->Position(); + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOCr4") , KErrMdEUnknownQueryType ); +#endif + User::Leave( KErrMdEUnknownQueryType ); + } + } + + iResults->PositionL( KNoOffset ); + itemIds.SerializeL( *iResults ); + + for( TInt i = 0; i < count; i++ ) + { + AddIdToContainerL( iResultIds[i] ); + } + } + +void CMdSSqlFindOperation::CreateDistinctL() + { + TMdCItemIds itemIds; + itemIds.iNamespaceDefId = iFindClause->NamespaceDef()->GetId(); + itemIds.iErrorCode = KErrNone; + itemIds.iObjectIds.iPtr.iCount = 0; + itemIds.iObjectIds.iPtr.iOffset = KNoOffset; + itemIds.iEventIds.iPtr.iCount = 0; + itemIds.iEventIds.iPtr.iOffset = KNoOffset; + itemIds.iRelationIds.iPtr.iCount = 0; + itemIds.iRelationIds.iPtr.iOffset = KNoOffset; + + itemIds.iObjectUris.iPtr.iCount = 0; + itemIds.iObjectUris.iPtr.iOffset = sizeof(TMdCItemIds); + + iResults->PositionL( itemIds.iObjectUris.iPtr.iOffset ); + const TInt resultRowsCount = iResultRows.Count(); + for ( TInt i = 0; i < resultRowsCount; ++i ) + { + if ( !iResultRows[i]->Column( 0 ).IsNull() ) + { + TPtrC16 value = TPtr16((TUint16*)0, 0); + iResultRows[i]->Column( 0 ).Get( value ); + iResults->InsertL( value ); + ++itemIds.iObjectUris.iPtr.iCount; + } + } + + iResults->PositionL( KNoOffset ); + itemIds.SerializeL( *iResults ); + } + +void CMdSSqlFindOperation::AddToContainerL() + { + // if old result buffer exist try to use it + if( iResults ) + { + // create new if the old result buffer is too short + if( iResults->Size() < iMemoryLimit ) + { + delete iResults; + iResults = NULL; + + iResults = CMdCSerializationBuffer::NewL( iMemoryLimit ); + } + // else just move to the begin of the result buffer + else + { + iResults->PositionL( 0 ); + } + } + else + { + iResults = CMdCSerializationBuffer::NewL( iMemoryLimit ); + } + + TInt err; + switch( iResultMode ) + { + case EQueryResultModeCount: + { + TRAP( err, CreateCountL() ); + break; + } + case EQueryResultModeItem: + { + TRAP( err, CreateItemL() ); + break; + } + case EQueryResultModeId: + { + TRAP( err, CreateIdL() ); + break; + } + case EQueryResultModeDistinctValues: + { + TRAP( err, CreateDistinctL() ); + break; + } + default: + { +#ifdef _DEBUG + User::Panic( _L("MdSFOAd3") , KErrMdEUnknownQueryResultMode ); +#endif + User::Leave( KErrMdEUnknownQueryResultMode ); + } + } + + if( err != KErrNone ) + { + delete iResults; + iResults = NULL; + } + + ConsumeRows(); + } + +TMdCOffset CMdSSqlFindOperation::AddObjectToContainerL( RRowData& aRow, TMdCOffset aFreespaceOffset ) + { + TMdCObject object; + const TMdCOffset objectOffset = iResults->Position(); + object.iFlags = EMdEObjectFlagNone; + + // Get base objects basic values + TUint32 serverSideFlags; + TPtrC16 uri; + aRow.Column( 0 ).Get( object.iId ); + aRow.Column( 1 ).Get( object.iDefId ); + aRow.Column( 2 ).Get( serverSideFlags ); + aRow.Column( 3 ).Get( object.iMediaId ); + aRow.Column( 4 ).Get( object.iUsageCount ); + aRow.Column( 5 ).Get( object.iGuidHigh ); + aRow.Column( 6 ).Get( object.iGuidLow ); + if (aRow.Column( 7 ).IsNull()) + { + object.iId = KNoId; + object.iUri.iPtr.iCount = 0; + object.iUri.iPtr.iOffset = KNoOffset; + object.SerializeL( *iResults ); + return aFreespaceOffset; + } + aRow.Column( 7 ).Get( uri ); + + // SETTING CLIENT SIDE FLAGS + // Set not present flag to client side flags + // (removed objects are also flaged as not present) + if( ( serverSideFlags & EMdEObjectFlagNotPresent ) || + ( serverSideFlags & EMdEObjectFlagRemoved ) ) + { + object.iFlags |= EMdEObjectFlagNotPresent; + } + + // Set confidential flag to client side flags + if( serverSideFlags & EMdEObjectFlagConfidential ) + { + object.iFlags |= EMdEObjectFlagConfidential; + } + + // Set freetext flag to client side flags + if( serverSideFlags & EMdEObjectFlagFreetexts ) + { + object.iFlags |= EMdEObjectFlagFreetexts; + } + + // Set placeholder flag to client side flags + if( serverSideFlags & EMdEObjectFlagPlaceholder ) + { + object.iFlags |= EMdEObjectFlagPlaceholder; + + // object is placeholder, so try add it's URI to harverting + // prioritization buffer + if( iHarvestingPrioritizationCount > 0 ) + { + iFind.Server().AddHarvestingPrioritizationUriL( uri ); + + iHarvestingPrioritizationCount--; + + if( iHarvestingPrioritizationCount == 0 ) + { + iFind.Server().NotifyHarvestingPrioritizationObserver( KErrNone ); + } + } + } + + const CMdsObjectDef* objectDef = iFindClause->ObjectDef(); + if( !objectDef ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOAd4") , KErrMdEUnknownObjectDef ); +#endif + User::Leave( KErrMdEUnknownObjectDef ); + } + + // Add base objects basic values to result buffer + object.iUri.iPtr.iCount = uri.Length(); + object.iUri.iPtr.iOffset = aFreespaceOffset; + iResults->PositionL( aFreespaceOffset ); + aFreespaceOffset = iResults->InsertL( uri ); + + const RPointerArray& propertyFilters = iFindClause->PropertyFilters(); + + // No property filters + if( propertyFilters.Count() <= 0 ) + { + const TInt allPropertyCount = objectDef->GetAllPropertiesCount(); + object.iProperties.iPtr.iCount = 0; + object.iProperties.iPtr.iOffset = aFreespaceOffset; + + // Position after property offsets + aFreespaceOffset += allPropertyCount * sizeof(TMdCProperty); + + for( TInt i = 0; i < allPropertyCount; i++ ) + { + const CMdsObjectDef::TMdsColumnOrder& propertyColumn = + objectDef->GetPropertyColumnL( i ); + + TColumn& column = aRow.Column( propertyColumn.iColumnId ); + + // check if property exists, else continue to with next property + if( column.IsNull() ) + { + continue; + } + + TMdCProperty property; + + property.iPropertyDefId = propertyColumn.iPropertyDef.GetId(); + property.iModFlags = EMdEPropertyModNone; + + const TPropertyType propertyType = propertyColumn.iPropertyDef.GetType(); + switch(propertyType) + { + case EPropertyBool: + { + TBool value; + column.Get( value ); + property.iValue.iInt32 = value; + } + break; + case EPropertyInt8: + { + TInt32 value32; + column.Get( value32 ); + property.iValue.iInt32 = value32; + } + break; + case EPropertyUint8: + { + TUint32 value32; + column.Get( value32 ); + property.iValue.iUint32 = value32; + } + break; + case EPropertyInt16: + { + TInt32 value32; + column.Get( value32 ); + property.iValue.iInt32 = value32; + } + break; + case EPropertyUint16: + { + TUint32 value32; + column.Get( value32 ); + property.iValue.iUint32 = value32; + } + break; + case EPropertyInt32: + { + TInt32 value; + column.Get( value ); + property.iValue.iInt32 = value; + } + break; + case EPropertyUint32: + { + TUint32 value; + column.Get( value ); + property.iValue.iUint32 = value; + } + break; + case EPropertyInt64: + { + TInt64 value; + column.Get( value ); + property.iValue.iInt64 = value; + } + break; + case EPropertyReal32: + { + TReal32 value; + column.Get( value ); + property.iValue.iReal = value; + } + break; + case EPropertyReal64: + { + TReal64 value; + column.Get( value ); + property.iValue.iReal = value; + } + break; + case EPropertyTime: + { + TTime value; + column.Get( value ); + property.iValue.iInt64 = value.Int64(); + } + break; + case EPropertyText: + { + TPtrC16 value; + column.Get( value ); + if (value.Length() > 0) + { + property.iValue.iPtr.iCount = value.Length(); + property.iValue.iPtr.iOffset = aFreespaceOffset; + iResults->PositionL( aFreespaceOffset ); + aFreespaceOffset = iResults->InsertL( value ); + } + else + { + property.iValue.iPtr.iCount = 0; + property.iValue.iPtr.iOffset = KNoOffset; + } + } + break; + default: +#ifdef _DEBUG + User::Panic( _L("MdSFOAd5") , KErrMdEUnknownPropertyType ); +#endif + User::Leave( KErrMdEUnknownPropertyType ); + } + + // store property in buffer + iResults->PositionL( object.iProperties.iPtr.iOffset + + object.iProperties.iPtr.iCount * sizeof(TMdCProperty) ); + ++object.iProperties.iPtr.iCount; + property.SerializeL( *iResults ); + } + } + // Property filters + else + { + const TUint32 propertyCount = propertyFilters.Count(); + object.iProperties.iPtr.iCount = 0; + object.iProperties.iPtr.iOffset = aFreespaceOffset; + + // Position after property offsets + aFreespaceOffset += propertyCount * sizeof(TMdCProperty); + + for( TInt i = 0; i < propertyCount; i++ ) + { + CMdsPropertyDef* propDef = propertyFilters[i]; + + if( !propDef ) + { +#ifdef _DEBUG + User::Panic( _L("MdSFOAd6") , KErrMdEUnknownPropertyDef ); +#endif + User::Leave( KErrMdEUnknownPropertyDef ); + } + + TColumn& column = aRow.Column( KBaseObjectBasicValueColumnOffset + i ); + + // check if property exists, else continue to with next property + if( column.IsNull() ) + { + continue; + } + + TMdCProperty property; + + property.iPropertyDefId = propDef->GetId(); + property.iModFlags = EMdEPropertyModNone; + + const TPropertyType propertyType = propDef->GetType(); + switch(propertyType) + { + case EPropertyBool: + { + TBool value; + column.Get( value ); + property.iValue.iInt32 = value; + } + break; + case EPropertyInt8: + { + TInt32 value32; + column.Get( value32 ); + property.iValue.iInt32 = value32; + } + break; + case EPropertyUint8: + { + TUint32 value32; + column.Get( value32 ); + property.iValue.iUint32 = value32; + } + break; + case EPropertyInt16: + { + TInt32 value32; + column.Get( value32 ); + property.iValue.iInt32 = value32; + } + break; + case EPropertyUint16: + { + TUint32 value32; + column.Get( value32 ); + property.iValue.iUint32 = value32; + } + break; + case EPropertyInt32: + { + TInt32 value; + column.Get( value ); + property.iValue.iInt32 = value; + } + break; + case EPropertyUint32: + { + TUint32 value; + column.Get( value ); + property.iValue.iUint32 = value; + } + break; + case EPropertyInt64: + { + TInt64 value; + column.Get( value ); + property.iValue.iInt64 = value; + } + break; + case EPropertyReal32: + { + TReal32 value; + column.Get( value ); + property.iValue.iReal = value; + } + break; + case EPropertyReal64: + { + TReal64 value; + column.Get( value ); + property.iValue.iReal = value; + } + break; + case EPropertyTime: + { + TTime value; + column.Get( value ); + property.iValue.iReal = value.Int64(); + } + break; + case EPropertyText: + { + TPtrC16 value; + column.Get( value ); + if (value.Length() > 0) + { + property.iValue.iPtr.iCount = value.Length(); + property.iValue.iPtr.iOffset = aFreespaceOffset; + iResults->PositionL( aFreespaceOffset ); + aFreespaceOffset = iResults->InsertL( value ); + } + else + { + property.iValue.iPtr.iCount = 0; + property.iValue.iPtr.iOffset = KNoOffset; + } + } + break; + default: +#ifdef _DEBUG + User::Panic( _L("MdSFOAd7") , KErrMdEUnknownPropertyType ); +#endif + User::Leave( KErrMdEUnknownPropertyType ); + } + + // store property in buffer + iResults->PositionL( object.iProperties.iPtr.iOffset + + object.iProperties.iPtr.iCount * sizeof(TMdCProperty) ); + ++object.iProperties.iPtr.iCount; + property.SerializeL( *iResults ); + } + } + + if( FindCriteria().IncludesFreetexts() ) + { + // In result row the second lastest column is free text count + const TInt freeTextCountColumn = aRow.Size() - 2; + + // Get free text count and total free text lenght. + TUint32 freeTextCount = 0; + aRow.Column( freeTextCountColumn ).Get( freeTextCount ); + + if( freeTextCount > 0 ) + { + object.iFreeTexts.iPtr.iCount = freeTextCount; + object.iFreeTexts.iPtr.iOffset = aFreespaceOffset; + + // In result row last column is total free text lenght. + const TInt totalFreeTextsLengthColumn = aRow.Size() - 1; + + TUint32 totalFreeTextsLength = 0; + aRow.Column( totalFreeTextsLengthColumn ).Get( totalFreeTextsLength ); + + // Reserve space for free texts. + // For every free text possible padding (TUint8), length (TUint16) + TUint32 freeTextReserve = freeTextCount * CMdCSerializationBuffer::KRequiredSizeForEmptyText; + // and total free text length * TUint16 + freeTextReserve += totalFreeTextsLength * sizeof( TUint16 ); + + aFreespaceOffset += freeTextReserve; + } + else + { + object.iFreeTexts.iPtr.iCount = 0; + object.iFreeTexts.iPtr.iOffset = KNoOffset; + } + } + else + { + object.iFreeTexts.iPtr.iCount = 0; + object.iFreeTexts.iPtr.iOffset = KNoOffset; + } + + iResults->PositionL( objectOffset ); + object.SerializeL( *iResults ); + + return aFreespaceOffset; + } + +void CMdSSqlFindOperation::ConsumeRows() + { + if( EQueryResultModeId != iResultMode ) + { + const TInt KRowCount = iResultRows.Count(); + + for( TInt i = 0; i < KRowCount; i++ ) + { + iResultRows[i]->Close(); + } + + iResultRows.ResetAndDestroy(); + } + // handle result mode IDs as special case + else + { + iResultIds.Reset(); + } + }