| sl@0 |      1 | // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
 | 
| sl@0 |      2 | // All rights reserved.
 | 
| sl@0 |      3 | // This component and the accompanying materials are made available
 | 
| sl@0 |      4 | // under the terms of "Eclipse Public License v1.0"
 | 
| sl@0 |      5 | // which accompanies this distribution, and is available
 | 
| sl@0 |      6 | // at the URL "http://www.eclipse.org/legal/epl-v10.html".
 | 
| sl@0 |      7 | //
 | 
| sl@0 |      8 | // Initial Contributors:
 | 
| sl@0 |      9 | // Nokia Corporation - initial contribution.
 | 
| sl@0 |     10 | //
 | 
| sl@0 |     11 | // Contributors:
 | 
| sl@0 |     12 | //
 | 
| sl@0 |     13 | // Description:
 | 
| sl@0 |     14 | //
 | 
| sl@0 |     15 | 
 | 
| sl@0 |     16 | #include "UT_STD.H"
 | 
| sl@0 |     17 | 
 | 
| sl@0 |     18 | // Class CDbReverseIterator
 | 
| sl@0 |     19 | 
 | 
| sl@0 |     20 | NONSHARABLE_CLASS(CDbReverseIter) : public CDbRecordIter
 | 
| sl@0 |     21 | 	{
 | 
| sl@0 |     22 | public:
 | 
| sl@0 |     23 | 	CDbReverseIter(CDbRecordIter* anIterator);
 | 
| sl@0 |     24 | 	~CDbReverseIter();
 | 
| sl@0 |     25 | private:
 | 
| sl@0 |     26 | 	TInt Count() const;
 | 
| sl@0 |     27 | 	TDbRecordId CurrentL();
 | 
| sl@0 |     28 | 	TBool GotoL(TDbPosition aPosition);
 | 
| sl@0 |     29 | 	TBool GotoL(TDbRecordId aRecordId,RDbTableRow& aBuffer);
 | 
| sl@0 |     30 | 	TBool SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison);
 | 
| sl@0 |     31 | 	TDeleted DoDeletedL(TDbPosition aPosition,TDbRecordId aRecordId,const RDbTableRow* aRow);
 | 
| sl@0 |     32 | private:
 | 
| sl@0 |     33 | 	CDbRecordIter* iIter;
 | 
| sl@0 |     34 | 	};
 | 
| sl@0 |     35 | 
 | 
| sl@0 |     36 | CDbReverseIter::CDbReverseIter(CDbRecordIter* aIterator)
 | 
| sl@0 |     37 | 	: CDbRecordIter(aIterator->Host()),iIter(aIterator)
 | 
| sl@0 |     38 | 	{}
 | 
| sl@0 |     39 | 
 | 
| sl@0 |     40 | CDbReverseIter::~CDbReverseIter()
 | 
| sl@0 |     41 | 	{
 | 
| sl@0 |     42 | 	delete iIter;
 | 
| sl@0 |     43 | 	}
 | 
| sl@0 |     44 | 
 | 
| sl@0 |     45 | TInt CDbReverseIter::Count() const
 | 
| sl@0 |     46 | 	{
 | 
| sl@0 |     47 | 	return iIter->Count();
 | 
| sl@0 |     48 | 	}
 | 
| sl@0 |     49 | 
 | 
| sl@0 |     50 | TDbRecordId CDbReverseIter::CurrentL()
 | 
| sl@0 |     51 | 	{
 | 
| sl@0 |     52 | 	return iIter->CurrentL();
 | 
| sl@0 |     53 | 	}
 | 
| sl@0 |     54 | 
 | 
| sl@0 |     55 | TBool CDbReverseIter::GotoL(TDbPosition aPosition)
 | 
| sl@0 |     56 | 	{
 | 
| sl@0 |     57 | 	return iIter->GotoL(TDbPosition(EDbLast-aPosition));
 | 
| sl@0 |     58 | 	}
 | 
| sl@0 |     59 | 
 | 
| sl@0 |     60 | TBool CDbReverseIter::GotoL(TDbRecordId aRecord,RDbTableRow& aRow)
 | 
| sl@0 |     61 | 	{
 | 
| sl@0 |     62 | 	return iIter->GotoL(aRecord,aRow);
 | 
| sl@0 |     63 | 	}
 | 
| sl@0 |     64 | 
 | 
| sl@0 |     65 | TBool CDbReverseIter::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison)
 | 
| sl@0 |     66 | //
 | 
| sl@0 |     67 | // Reverse the comparison
 | 
| sl@0 |     68 | //
 | 
| sl@0 |     69 | 	{
 | 
| sl@0 |     70 | 	return iIter->SeekL(aKey,RDbTable::TComparison(RDbTable::EGreaterThan-aComparison));
 | 
| sl@0 |     71 | 	}
 | 
| sl@0 |     72 | 
 | 
| sl@0 |     73 | CDbReverseIter::TDeleted CDbReverseIter::DoDeletedL(TDbPosition aPosition,TDbRecordId aRecordId,const RDbTableRow* aRow)
 | 
| sl@0 |     74 | //
 | 
| sl@0 |     75 | // Need to invert the position.
 | 
| sl@0 |     76 | //
 | 
| sl@0 |     77 | 	{
 | 
| sl@0 |     78 | 	return iIter->DoDeletedL(TDbPosition(EDbLast-aPosition),aRecordId,aRow);
 | 
| sl@0 |     79 | 	}
 | 
| sl@0 |     80 | 
 | 
| sl@0 |     81 | // Class CDbTableSource
 | 
| sl@0 |     82 | 
 | 
| sl@0 |     83 | CDbTableSource::CDbTableSource()
 | 
| sl@0 |     84 | 	{}
 | 
| sl@0 |     85 | 
 | 
| sl@0 |     86 | CDbTableSource::~CDbTableSource()
 | 
| sl@0 |     87 | 	{
 | 
| sl@0 |     88 | 	delete iIter;
 | 
| sl@0 |     89 | 	iRow.Close();
 | 
| sl@0 |     90 | 	}
 | 
| sl@0 |     91 | 
 | 
| sl@0 |     92 | void CDbTableSource::Construct(CDbTable* aTable)
 | 
| sl@0 |     93 | //
 | 
| sl@0 |     94 | // We own the table pass in
 | 
| sl@0 |     95 | //
 | 
| sl@0 |     96 | 	{
 | 
| sl@0 |     97 | 	iIterMark.Construct(aTable->Generation());
 | 
| sl@0 |     98 | 	iRow.Open(aTable);
 | 
| sl@0 |     99 | 	}
 | 
| sl@0 |    100 | 
 | 
| sl@0 |    101 | void CDbTableSource::ReverseIteratorL()
 | 
| sl@0 |    102 | //
 | 
| sl@0 |    103 | // Plug in a reverse iterator adaptor for the iterator
 | 
| sl@0 |    104 | //
 | 
| sl@0 |    105 | 	{
 | 
| sl@0 |    106 | 	iIter=new(ELeave) CDbReverseIter(iIter);
 | 
| sl@0 |    107 | 	}
 | 
| sl@0 |    108 | 
 | 
| sl@0 |    109 | TInt CDbTableSource::ColumnCount() const
 | 
| sl@0 |    110 | 	{
 | 
| sl@0 |    111 | 	return iRow.Table().Def().Columns().Count();
 | 
| sl@0 |    112 | 	}
 | 
| sl@0 |    113 | 
 | 
| sl@0 |    114 | const TDbColumnDef& CDbTableSource::ColumnDef(TDbColNo aCol) const
 | 
| sl@0 |    115 | 	{
 | 
| sl@0 |    116 | 	return iRow.Table().Def().Columns()[aCol];
 | 
| sl@0 |    117 | 	}
 | 
| sl@0 |    118 | 
 | 
| sl@0 |    119 | RDbRow* CDbTableSource::RowBuffer()
 | 
| sl@0 |    120 | 	{
 | 
| sl@0 |    121 | 	return &iRow;
 | 
| sl@0 |    122 | 	}
 | 
| sl@0 |    123 | 
 | 
| sl@0 |    124 | TDbColumn CDbTableSource::Column(TDbColNo aColNo)
 | 
| sl@0 |    125 | 	{
 | 
| sl@0 |    126 | 	return TDbColumn(iRow,aColNo);
 | 
| sl@0 |    127 | 	}
 | 
| sl@0 |    128 | 
 | 
| sl@0 |    129 | void CDbTableSource::Reset()
 | 
| sl@0 |    130 | 	{
 | 
| sl@0 |    131 | 	iReset=ETrue;
 | 
| sl@0 |    132 | 	}
 | 
| sl@0 |    133 | 
 | 
| sl@0 |    134 | TBool CDbTableSource::EvaluateL(TInt&,TDbRecordId&,TBool&)
 | 
| sl@0 |    135 | 	{
 | 
| sl@0 |    136 | 	return EFalse;
 | 
| sl@0 |    137 | 	}
 | 
| sl@0 |    138 | 
 | 
| sl@0 |    139 | TBool CDbTableSource::Unevaluated()
 | 
| sl@0 |    140 | 	{
 | 
| sl@0 |    141 | 	return EFalse;
 | 
| sl@0 |    142 | 	}
 | 
| sl@0 |    143 | 
 | 
| sl@0 |    144 | TInt CDbTableSource::CountL()
 | 
| sl@0 |    145 | //
 | 
| sl@0 |    146 | // Count the records
 | 
| sl@0 |    147 | //
 | 
| sl@0 |    148 | 	{
 | 
| sl@0 |    149 | 	if (iReset)
 | 
| sl@0 |    150 | 		OpenIteratorL();
 | 
| sl@0 |    151 | 	return iIter->Count();
 | 
| sl@0 |    152 | 	}
 | 
| sl@0 |    153 | 
 | 
| sl@0 |    154 | void CDbTableSource::OpenIteratorL()
 | 
| sl@0 |    155 | //
 | 
| sl@0 |    156 | // Re-open the iterator after a reset
 | 
| sl@0 |    157 | //
 | 
| sl@0 |    158 | 	{
 | 
| sl@0 |    159 | 	__ASSERT(iIter);
 | 
| sl@0 |    160 | 	if (iIter->Host().OpenL())
 | 
| sl@0 |    161 | 		__LEAVE(KErrCorrupt);
 | 
| sl@0 |    162 | 	iReset=EFalse;
 | 
| sl@0 |    163 | 	}
 | 
| sl@0 |    164 | 
 | 
| sl@0 |    165 | CDbTableSource::TGoto CDbTableSource::GotoL(TInt& aWork,TDbPosition aPosition,TDbRecordId& aRecordId)
 | 
| sl@0 |    166 | //
 | 
| sl@0 |    167 | // Move to the position specified. If out of synch, try to resynch the iterator
 | 
| sl@0 |    168 | // using aRecordId
 | 
| sl@0 |    169 | //
 | 
| sl@0 |    170 | 	{
 | 
| sl@0 |    171 | 	__ASSERT(iIter);
 | 
| sl@0 |    172 | 	TInt work=aWork;
 | 
| sl@0 |    173 | 	if (work<0)
 | 
| sl@0 |    174 | 		return EExhausted;
 | 
| sl@0 |    175 | 	aWork=work-EWorkToIterate;
 | 
| sl@0 |    176 | 	CDbRecordIter& iter=*iIter;
 | 
| sl@0 |    177 | 	if (iIterMark.Changed())
 | 
| sl@0 |    178 | 		{	// two possible resaons for this
 | 
| sl@0 |    179 | 		if (iReset)
 | 
| sl@0 |    180 | 			OpenIteratorL();
 | 
| sl@0 |    181 | 		if (aPosition==EDbNext || aPosition==EDbPrevious)
 | 
| sl@0 |    182 | 			{	// table modified
 | 
| sl@0 |    183 | 			if (aRecordId==KDbNullRecordId)
 | 
| sl@0 |    184 | 				return ESynchFailure;
 | 
| sl@0 |    185 | 			if (!iter.GotoL(aRecordId,iRow))
 | 
| sl@0 |    186 | 				{	// record has been deleted
 | 
| sl@0 |    187 | 				switch(iter.DeletedL(aPosition,aRecordId))
 | 
| sl@0 |    188 | 					{
 | 
| sl@0 |    189 | 				case CDbRecordIter::EAtRow:			// found it
 | 
| sl@0 |    190 | 					aRecordId=iter.CurrentL();
 | 
| sl@0 |    191 | 					return ESuccess;
 | 
| sl@0 |    192 | 				case CDbRecordIter::ENoRow:			// no more rows
 | 
| sl@0 |    193 | 					aRecordId=KDbNullRecordId;
 | 
| sl@0 |    194 | 					return ENoRow;
 | 
| sl@0 |    195 | 				case CDbRecordIter::ENotSupported:	// couldn't re-snych
 | 
| sl@0 |    196 | 					return ESynchFailure;
 | 
| sl@0 |    197 | 					}
 | 
| sl@0 |    198 | 				}
 | 
| sl@0 |    199 | 			}
 | 
| sl@0 |    200 | 		iIterMark.Mark();
 | 
| sl@0 |    201 | 		}
 | 
| sl@0 |    202 | 	if (iter.GotoL(aPosition))
 | 
| sl@0 |    203 | 		{
 | 
| sl@0 |    204 | 		aRecordId=iter.CurrentL();
 | 
| sl@0 |    205 | 		return ESuccess;
 | 
| sl@0 |    206 | 		}
 | 
| sl@0 |    207 | 	else
 | 
| sl@0 |    208 | 		{
 | 
| sl@0 |    209 | 		aRecordId=KDbNullRecordId;
 | 
| sl@0 |    210 | 		return ENoRow;
 | 
| sl@0 |    211 | 		}
 | 
| sl@0 |    212 | 	}
 | 
| sl@0 |    213 | 
 | 
| sl@0 |    214 | TBool CDbTableSource::SynchL(TDbRecordId aRecordId)
 | 
| sl@0 |    215 | 	{
 | 
| sl@0 |    216 | 	if (iReset)
 | 
| sl@0 |    217 | 		OpenIteratorL();
 | 
| sl@0 |    218 | 	TBool found=iIter->GotoL(aRecordId,iRow);
 | 
| sl@0 |    219 | 	iIterMark.Mark();
 | 
| sl@0 |    220 | 	return found;
 | 
| sl@0 |    221 | 	}
 | 
| sl@0 |    222 | 
 | 
| sl@0 |    223 | TBool CDbTableSource::GotoL(TDbRecordId aRecordId)
 | 
| sl@0 |    224 | 	{
 | 
| sl@0 |    225 | 	return iRow.Table().ExistsL(aRecordId) ? SynchL(aRecordId) : EFalse;
 | 
| sl@0 |    226 | 	}
 | 
| sl@0 |    227 | 
 | 
| sl@0 |    228 | void CDbTableSource::ReadRowL(TDbRecordId aRecordId)
 | 
| sl@0 |    229 | 	{
 | 
| sl@0 |    230 | 	iRow.ReadL(aRecordId);
 | 
| sl@0 |    231 | 	}
 | 
| sl@0 |    232 | 
 | 
| sl@0 |    233 | void CDbTableSource::NewRowL(TDbRecordId aCopyRecord)
 | 
| sl@0 |    234 | 	{
 | 
| sl@0 |    235 | 	if (iIter!=NULL&&iReset)
 | 
| sl@0 |    236 | 		OpenIteratorL();
 | 
| sl@0 |    237 | 	iRow.NewL(aCopyRecord);
 | 
| sl@0 |    238 | 	}
 | 
| sl@0 |    239 | 
 | 
| sl@0 |    240 | void CDbTableSource::PrepareToWriteRowL(TWrite aWrite)
 | 
| sl@0 |    241 | 	{
 | 
| sl@0 |    242 | 	__ASSERT(aWrite==EReplace||aWrite==EAppend);
 | 
| sl@0 |    243 | 	if (aWrite==EReplace)
 | 
| sl@0 |    244 | 		iRow.PrepareReplaceL();
 | 
| sl@0 |    245 | 	else
 | 
| sl@0 |    246 | 		iRow.PrepareAppendL();
 | 
| sl@0 |    247 | 	}
 | 
| sl@0 |    248 | 
 | 
| sl@0 |    249 | TDbRecordId CDbTableSource::WriteRowL(TWrite aWrite,TSynch aSynch)
 | 
| sl@0 |    250 | 	{
 | 
| sl@0 |    251 | 	__ASSERT(aWrite==EReplace||aWrite==EAppend);
 | 
| sl@0 |    252 | 	TDbRecordId id=aWrite==EReplace ? iRow.ReplaceL() : iRow.AppendL();
 | 
| sl@0 |    253 | 	if (aSynch==ESynch)
 | 
| sl@0 |    254 | 		{
 | 
| sl@0 |    255 | 		__DEBUG(TBool dbgchk=) SynchL(id);
 | 
| sl@0 |    256 | 		__ASSERT(dbgchk);
 | 
| sl@0 |    257 | 		}
 | 
| sl@0 |    258 | 	return id;
 | 
| sl@0 |    259 | 	}
 | 
| sl@0 |    260 | 
 | 
| sl@0 |    261 | CDbTableSource::TDelete CDbTableSource::DeleteRowL(TDbRecordId& aRecordId,TSynch aSynch)
 | 
| sl@0 |    262 | //
 | 
| sl@0 |    263 | // Remove the row from the table. Synchronise the iterator if required
 | 
| sl@0 |    264 | // When not synchronising, the return value is not significant
 | 
| sl@0 |    265 | //
 | 
| sl@0 |    266 | 	{
 | 
| sl@0 |    267 | 	// if the table has changed, we may need to re-synch the iterator before deleting
 | 
| sl@0 |    268 | 	// this is important if neighbouring rows have been deleted by another view
 | 
| sl@0 |    269 | 	if (aSynch==ESynch && iIterMark.Changed() && !SynchL(aRecordId))
 | 
| sl@0 |    270 | 		__LEAVE(KErrNotFound);		// it has been deleted already!
 | 
| sl@0 |    271 | 	iRow.DeleteL(aRecordId);
 | 
| sl@0 |    272 | 	if (aSynch==ESynch)
 | 
| sl@0 |    273 | 		{
 | 
| sl@0 |    274 | 		CDbRecordIter::TDeleted del=iIter->DeletedL(EDbNext,aRecordId,iRow);
 | 
| sl@0 |    275 | 		__ASSERT(del!=CDbRecordIter::ENotSupported);	// must always be able to synch with row data
 | 
| sl@0 |    276 | 		iIterMark.Mark();
 | 
| sl@0 |    277 | 		if (del==CDbRecordIter::EAtRow)
 | 
| sl@0 |    278 | 			{	// pass back the next record id
 | 
| sl@0 |    279 | 			aRecordId=iIter->CurrentL();
 | 
| sl@0 |    280 | 			return EDeletedAtNext;
 | 
| sl@0 |    281 | 			}
 | 
| sl@0 |    282 | 		}
 | 
| sl@0 |    283 | 	return EDeletedAtEnd;
 | 
| sl@0 |    284 | 	}
 | 
| sl@0 |    285 | 
 | 
| sl@0 |    286 | void CDbTableSource::SetIndexL(const TDesC* anIndex)
 | 
| sl@0 |    287 | 	{
 | 
| sl@0 |    288 | 	CDbRecordIter* iter=anIndex ? iRow.Table().IteratorL(*anIndex) : iRow.Table().IteratorL();
 | 
| sl@0 |    289 | 	delete iIter;
 | 
| sl@0 |    290 | 	iIter=iter;
 | 
| sl@0 |    291 | 	}
 | 
| sl@0 |    292 | 
 | 
| sl@0 |    293 | TBool CDbTableSource::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison,TDbRecordId& aRecordId)
 | 
| sl@0 |    294 | 	{
 | 
| sl@0 |    295 | 	if (iReset)
 | 
| sl@0 |    296 | 		OpenIteratorL();
 | 
| sl@0 |    297 | 	CDbRecordIter& iter=*iIter;
 | 
| sl@0 |    298 | 	TBool atrow=iter.SeekL(aKey,aComparison);
 | 
| sl@0 |    299 | 	aRecordId=atrow ? iter.CurrentL() : KDbNullRecordId;
 | 
| sl@0 |    300 | 	iIterMark.Mark();
 | 
| sl@0 |    301 | 	return atrow;
 | 
| sl@0 |    302 | 	}
 | 
| sl@0 |    303 | 
 | 
| sl@0 |    304 | CSqlSearchCondition* CDbTableSource::ParseConstraintLC(const TDesC& aCondition)
 | 
| sl@0 |    305 | 	{
 | 
| sl@0 |    306 | 	CSqlSearchCondition* sc=Sql::ParseSearchConditionLC(aCondition);
 | 
| sl@0 |    307 | 	sc->BindL(iRow);
 | 
| sl@0 |    308 | 	return sc;
 | 
| sl@0 |    309 | 	}
 |