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