sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "UT_STD.H" sl@0: sl@0: // Class CDbReverseIterator sl@0: sl@0: NONSHARABLE_CLASS(CDbReverseIter) : public CDbRecordIter sl@0: { sl@0: public: sl@0: CDbReverseIter(CDbRecordIter* anIterator); sl@0: ~CDbReverseIter(); sl@0: private: sl@0: TInt Count() const; sl@0: TDbRecordId CurrentL(); sl@0: TBool GotoL(TDbPosition aPosition); sl@0: TBool GotoL(TDbRecordId aRecordId,RDbTableRow& aBuffer); sl@0: TBool SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison); sl@0: TDeleted DoDeletedL(TDbPosition aPosition,TDbRecordId aRecordId,const RDbTableRow* aRow); sl@0: private: sl@0: CDbRecordIter* iIter; sl@0: }; sl@0: sl@0: CDbReverseIter::CDbReverseIter(CDbRecordIter* aIterator) sl@0: : CDbRecordIter(aIterator->Host()),iIter(aIterator) sl@0: {} sl@0: sl@0: CDbReverseIter::~CDbReverseIter() sl@0: { sl@0: delete iIter; sl@0: } sl@0: sl@0: TInt CDbReverseIter::Count() const sl@0: { sl@0: return iIter->Count(); sl@0: } sl@0: sl@0: TDbRecordId CDbReverseIter::CurrentL() sl@0: { sl@0: return iIter->CurrentL(); sl@0: } sl@0: sl@0: TBool CDbReverseIter::GotoL(TDbPosition aPosition) sl@0: { sl@0: return iIter->GotoL(TDbPosition(EDbLast-aPosition)); sl@0: } sl@0: sl@0: TBool CDbReverseIter::GotoL(TDbRecordId aRecord,RDbTableRow& aRow) sl@0: { sl@0: return iIter->GotoL(aRecord,aRow); sl@0: } sl@0: sl@0: TBool CDbReverseIter::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison) sl@0: // sl@0: // Reverse the comparison sl@0: // sl@0: { sl@0: return iIter->SeekL(aKey,RDbTable::TComparison(RDbTable::EGreaterThan-aComparison)); sl@0: } sl@0: sl@0: CDbReverseIter::TDeleted CDbReverseIter::DoDeletedL(TDbPosition aPosition,TDbRecordId aRecordId,const RDbTableRow* aRow) sl@0: // sl@0: // Need to invert the position. sl@0: // sl@0: { sl@0: return iIter->DoDeletedL(TDbPosition(EDbLast-aPosition),aRecordId,aRow); sl@0: } sl@0: sl@0: // Class CDbTableSource sl@0: sl@0: CDbTableSource::CDbTableSource() sl@0: {} sl@0: sl@0: CDbTableSource::~CDbTableSource() sl@0: { sl@0: delete iIter; sl@0: iRow.Close(); sl@0: } sl@0: sl@0: void CDbTableSource::Construct(CDbTable* aTable) sl@0: // sl@0: // We own the table pass in sl@0: // sl@0: { sl@0: iIterMark.Construct(aTable->Generation()); sl@0: iRow.Open(aTable); sl@0: } sl@0: sl@0: void CDbTableSource::ReverseIteratorL() sl@0: // sl@0: // Plug in a reverse iterator adaptor for the iterator sl@0: // sl@0: { sl@0: iIter=new(ELeave) CDbReverseIter(iIter); sl@0: } sl@0: sl@0: TInt CDbTableSource::ColumnCount() const sl@0: { sl@0: return iRow.Table().Def().Columns().Count(); sl@0: } sl@0: sl@0: const TDbColumnDef& CDbTableSource::ColumnDef(TDbColNo aCol) const sl@0: { sl@0: return iRow.Table().Def().Columns()[aCol]; sl@0: } sl@0: sl@0: RDbRow* CDbTableSource::RowBuffer() sl@0: { sl@0: return &iRow; sl@0: } sl@0: sl@0: TDbColumn CDbTableSource::Column(TDbColNo aColNo) sl@0: { sl@0: return TDbColumn(iRow,aColNo); sl@0: } sl@0: sl@0: void CDbTableSource::Reset() sl@0: { sl@0: iReset=ETrue; sl@0: } sl@0: sl@0: TBool CDbTableSource::EvaluateL(TInt&,TDbRecordId&,TBool&) sl@0: { sl@0: return EFalse; sl@0: } sl@0: sl@0: TBool CDbTableSource::Unevaluated() sl@0: { sl@0: return EFalse; sl@0: } sl@0: sl@0: TInt CDbTableSource::CountL() sl@0: // sl@0: // Count the records sl@0: // sl@0: { sl@0: if (iReset) sl@0: OpenIteratorL(); sl@0: return iIter->Count(); sl@0: } sl@0: sl@0: void CDbTableSource::OpenIteratorL() sl@0: // sl@0: // Re-open the iterator after a reset sl@0: // sl@0: { sl@0: __ASSERT(iIter); sl@0: if (iIter->Host().OpenL()) sl@0: __LEAVE(KErrCorrupt); sl@0: iReset=EFalse; sl@0: } sl@0: sl@0: CDbTableSource::TGoto CDbTableSource::GotoL(TInt& aWork,TDbPosition aPosition,TDbRecordId& aRecordId) sl@0: // sl@0: // Move to the position specified. If out of synch, try to resynch the iterator sl@0: // using aRecordId sl@0: // sl@0: { sl@0: __ASSERT(iIter); sl@0: TInt work=aWork; sl@0: if (work<0) sl@0: return EExhausted; sl@0: aWork=work-EWorkToIterate; sl@0: CDbRecordIter& iter=*iIter; sl@0: if (iIterMark.Changed()) sl@0: { // two possible resaons for this sl@0: if (iReset) sl@0: OpenIteratorL(); sl@0: if (aPosition==EDbNext || aPosition==EDbPrevious) sl@0: { // table modified sl@0: if (aRecordId==KDbNullRecordId) sl@0: return ESynchFailure; sl@0: if (!iter.GotoL(aRecordId,iRow)) sl@0: { // record has been deleted sl@0: switch(iter.DeletedL(aPosition,aRecordId)) sl@0: { sl@0: case CDbRecordIter::EAtRow: // found it sl@0: aRecordId=iter.CurrentL(); sl@0: return ESuccess; sl@0: case CDbRecordIter::ENoRow: // no more rows sl@0: aRecordId=KDbNullRecordId; sl@0: return ENoRow; sl@0: case CDbRecordIter::ENotSupported: // couldn't re-snych sl@0: return ESynchFailure; sl@0: } sl@0: } sl@0: } sl@0: iIterMark.Mark(); sl@0: } sl@0: if (iter.GotoL(aPosition)) sl@0: { sl@0: aRecordId=iter.CurrentL(); sl@0: return ESuccess; sl@0: } sl@0: else sl@0: { sl@0: aRecordId=KDbNullRecordId; sl@0: return ENoRow; sl@0: } sl@0: } sl@0: sl@0: TBool CDbTableSource::SynchL(TDbRecordId aRecordId) sl@0: { sl@0: if (iReset) sl@0: OpenIteratorL(); sl@0: TBool found=iIter->GotoL(aRecordId,iRow); sl@0: iIterMark.Mark(); sl@0: return found; sl@0: } sl@0: sl@0: TBool CDbTableSource::GotoL(TDbRecordId aRecordId) sl@0: { sl@0: return iRow.Table().ExistsL(aRecordId) ? SynchL(aRecordId) : EFalse; sl@0: } sl@0: sl@0: void CDbTableSource::ReadRowL(TDbRecordId aRecordId) sl@0: { sl@0: iRow.ReadL(aRecordId); sl@0: } sl@0: sl@0: void CDbTableSource::NewRowL(TDbRecordId aCopyRecord) sl@0: { sl@0: if (iIter!=NULL&&iReset) sl@0: OpenIteratorL(); sl@0: iRow.NewL(aCopyRecord); sl@0: } sl@0: sl@0: void CDbTableSource::PrepareToWriteRowL(TWrite aWrite) sl@0: { sl@0: __ASSERT(aWrite==EReplace||aWrite==EAppend); sl@0: if (aWrite==EReplace) sl@0: iRow.PrepareReplaceL(); sl@0: else sl@0: iRow.PrepareAppendL(); sl@0: } sl@0: sl@0: TDbRecordId CDbTableSource::WriteRowL(TWrite aWrite,TSynch aSynch) sl@0: { sl@0: __ASSERT(aWrite==EReplace||aWrite==EAppend); sl@0: TDbRecordId id=aWrite==EReplace ? iRow.ReplaceL() : iRow.AppendL(); sl@0: if (aSynch==ESynch) sl@0: { sl@0: __DEBUG(TBool dbgchk=) SynchL(id); sl@0: __ASSERT(dbgchk); sl@0: } sl@0: return id; sl@0: } sl@0: sl@0: CDbTableSource::TDelete CDbTableSource::DeleteRowL(TDbRecordId& aRecordId,TSynch aSynch) sl@0: // sl@0: // Remove the row from the table. Synchronise the iterator if required sl@0: // When not synchronising, the return value is not significant sl@0: // sl@0: { sl@0: // if the table has changed, we may need to re-synch the iterator before deleting sl@0: // this is important if neighbouring rows have been deleted by another view sl@0: if (aSynch==ESynch && iIterMark.Changed() && !SynchL(aRecordId)) sl@0: __LEAVE(KErrNotFound); // it has been deleted already! sl@0: iRow.DeleteL(aRecordId); sl@0: if (aSynch==ESynch) sl@0: { sl@0: CDbRecordIter::TDeleted del=iIter->DeletedL(EDbNext,aRecordId,iRow); sl@0: __ASSERT(del!=CDbRecordIter::ENotSupported); // must always be able to synch with row data sl@0: iIterMark.Mark(); sl@0: if (del==CDbRecordIter::EAtRow) sl@0: { // pass back the next record id sl@0: aRecordId=iIter->CurrentL(); sl@0: return EDeletedAtNext; sl@0: } sl@0: } sl@0: return EDeletedAtEnd; sl@0: } sl@0: sl@0: void CDbTableSource::SetIndexL(const TDesC* anIndex) sl@0: { sl@0: CDbRecordIter* iter=anIndex ? iRow.Table().IteratorL(*anIndex) : iRow.Table().IteratorL(); sl@0: delete iIter; sl@0: iIter=iter; sl@0: } sl@0: sl@0: TBool CDbTableSource::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison,TDbRecordId& aRecordId) sl@0: { sl@0: if (iReset) sl@0: OpenIteratorL(); sl@0: CDbRecordIter& iter=*iIter; sl@0: TBool atrow=iter.SeekL(aKey,aComparison); sl@0: aRecordId=atrow ? iter.CurrentL() : KDbNullRecordId; sl@0: iIterMark.Mark(); sl@0: return atrow; sl@0: } sl@0: sl@0: CSqlSearchCondition* CDbTableSource::ParseConstraintLC(const TDesC& aCondition) sl@0: { sl@0: CSqlSearchCondition* sc=Sql::ParseSearchConditionLC(aCondition); sl@0: sc->BindL(iRow); sl@0: return sc; sl@0: }