metadataengine/server/src/mdssqlfindoperation.cpp
changeset 0 c53acadfccc6
child 15 3cebc1a84278
--- /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<CMdsSchema&>(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<CMdsPropertyDef>& 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<CMdsPropertyDef>& 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<HBufC>& 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<CMdsPropertyDef>& 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();
+		}
+	}