First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // DBMS server proxy cursor
20 const TDbBlobId KUnknownBlobId=~0u;
27 static HDbsColumns* NewL(TInt aCount);
28 inline void Set(const TUint8* aPtr);
30 inline TInt Count() const;
31 inline TDbColType Type(TDbColNo aCol) const;
32 void Check(TDbColNo aCol) const;
34 inline HDbsColumns(TInt aCount);
40 inline HDbsColumns::HDbsColumns(TInt aCount)
43 inline void HDbsColumns::Set(const TUint8* aPtr)
44 {Mem::Copy(iType,aPtr,iCount);}
45 inline TPtr8 HDbsColumns::Ptr()
46 {return TPtr8(iType,iCount);}
47 inline TInt HDbsColumns::Count() const
49 inline TDbColType HDbsColumns::Type(TDbColNo aCol) const
50 {__DEBUG(Check(aCol));return TDbColType(iType[aCol-1]);}
52 HDbsColumns* HDbsColumns::NewL(TInt aCount)
54 return new(User::AllocL(_FOFF(HDbsColumns,iType[aCount]))) HDbsColumns(aCount);
57 void HDbsColumns::Check(TDbColNo aColNo) const
59 __ASSERT_ALWAYS(aColNo>0&&aColNo<=iCount,Panic(EDbsInvalidColumn));
64 CDbsCursor::CDbsCursor()
68 CDbsCursor* CDbsCursor::NewL(const RDbsObject& aDbs,TDbsFunction aFunction,TIpcArgs& aArgs)
70 CDbsCursor* self=new(ELeave) CDbsCursor;
71 CleanupStack::PushL(self);
72 self->ConstructL(aDbs,aFunction,aArgs);
77 void CDbsCursor::ConstructL(const RDbsObject& aDbs,TDbsFunction aFunction,TIpcArgs& aArgs)
79 // construct a cursor from the supplied parameters
80 // Retrieve the column types, in one pass if possible
83 TPckgBuf<TDbsColumns> cols;
85 iObject.OpenL(aDbs,aFunction,aArgs);
86 iColumns=HDbsColumns::NewL(cols().iCount);
87 if (cols().iCount<=cols().EMax)
88 iColumns->Set(cols().iData); // we have the column types
90 { // too many for the fixed buffer, make a second call to get the columns
91 TPtr8 ptr=iColumns->Ptr();
93 iObject.SendReceiveL(EDbsCursorColumnTypes,aArgs);
97 CDbsCursor::~CDbsCursor()
104 TDbColType CDbsCursor::Type(TDbColNo aCol) const
106 iColumns->Check(aCol);
107 return iColumns->Type(aCol);
110 void CDbsCursor::Reset()
113 iObject.SendReceive(EDbsCursorReset);
116 TBool CDbsCursor::EvaluateL()
119 return iObject.SendReceiveL(EDbsCursorEvaluate);
122 void CDbsCursor::Evaluate(TRequestStatus& aStatus)
125 iObject.SendReceive(EDbsCursorEvaluate,aStatus);
128 TBool CDbsCursor::Unevaluated()
130 return iObject.SendReceive(EDbsCursorUnevaluated);
133 void CDbsCursor::SetIndexL(const TDesC* anIndex)
135 iObject.SendReceiveL(EDbsCursorSetIndex,TIpcArgs(anIndex));
139 TBool CDbsCursor::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison)
141 TPtrC8 key(TDbsParam::PrepareLC(aKey));
143 TBool found=iObject.SendReceiveL(EDbsCursorSeek,TIpcArgs(&key,key.Length(),aComparison));
144 CleanupStack::PopAndDestroy(); // key
150 TBool CDbsCursor::AtBeginning()
152 if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtBeginning)>0)
154 return iState==EAtBeginning;
157 TBool CDbsCursor::AtEnd()
159 if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtEnd)>0)
161 return iState==EAtEnd;
164 TBool CDbsCursor::AtRow()
166 if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtRow)>0)
168 return iState>=EAtRow;
171 TInt CDbsCursor::CountL(RDbRowSet::TAccuracy aAccuracy)
173 // valid response is >=0 + undefined (==-1)
174 // server returns +1 for non-error conditions
177 return iObject.SendReceiveL(EDbsCursorCount,TIpcArgs(aAccuracy))-1;
180 TBool CDbsCursor::GotoL(RDbRowSet::TPosition aPosition)
182 TBool atrow=RetrieveL(EDbsCursorGotoPos,aPosition);
191 case RDbRowSet::EEnd:
192 case RDbRowSet::EFirst:
193 case RDbRowSet::ENext:
196 case RDbRowSet::EBeginning:
197 case RDbRowSet::ELast:
198 case RDbRowSet::EPrevious:
206 void CDbsCursor::Bookmark(TDbBookmark::TMark& aMark)
208 TPckg<TDbBookmark::TMark> pckg(aMark);
209 iObject.SendReceive(EDbsCursorBookmark,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,&pckg));
212 void CDbsCursor::GotoL(const TDbBookmark::TMark& aMark)
214 TPckgC<TDbBookmark::TMark> pckg(aMark);
216 iObject.SendReceiveL(EDbsCursorGotoBookmark,TIpcArgs(&pckg));
219 LOCAL_C void CancelCursor(TAny* aPtr)
221 STATIC_CAST(CDbCursor*,aPtr)->Cancel();
224 TBool CDbsCursor::RetrieveL(TDbsFunction aFunction,TInt aArg0)
226 // Read the row buffer
233 TInt max=iRow.MaxSize();
234 TPtr8 row((TUint8*)iRow.First(),max);
235 size=iObject.SendReceiveL(aFunction,TIpcArgs(aArg0,TIpcArgs::ENothing,max,&row))-1;
237 return EFalse; // no row to retrieve
240 // didn't fit! Grow the buffer
241 if (aFunction!=EDbsCursorRetrieveRow)
243 CleanupStack::PushL(TCleanupItem(CancelCursor,this)); // in case this goes wrong!
244 aFunction=EDbsCursorRetrieveRow;
249 if (aFunction==EDbsCursorRetrieveRow)
254 void CDbsCursor::GetL()
256 if (iState!=ERetrieve)
257 RetrieveL(EDbsCursorGet);
261 void CDbsCursor::InsertL(TInsert aClearRow)
263 RetrieveL(EDbsCursorInsert,aClearRow);
268 void CDbsCursor::UpdateL()
270 RetrieveL(EDbsCursorUpdate);
275 void CDbsCursor::Cancel()
277 if (iState==EUnknown || iState==EWrite)
278 iObject.SendReceive(EDbsCursorCancel);
281 void CDbsCursor::PutL()
283 TInt size=iRow.Size();
284 TPtrC8 row((const TUint8*)iRow.First(),size);
285 iObject.SendReceiveL(EDbsCursorPut,TIpcArgs(&row,size,iChangedBlob));// if iChangedBlob false, server can optimize put
286 iState=ERead; // we can still look at the row we put
289 void CDbsCursor::DeleteL()
292 iObject.SendReceiveL(EDbsCursorDelete);
295 TInt CDbsCursor::ColumnCount()
297 return iColumns->Count();
300 void CDbsCursor::ColumnsL(CDbColSet& aColSet)
302 // optimise the retreival of all columns
306 RReadStream in(HDbsBuf::NewLC(iObject,EDbsCursorColumns,m));
308 CleanupStack::PopAndDestroy(); // buffer
311 void CDbsCursor::ColumnDef(TDbCol& aCol,TDbColNo aColNo)
313 TPckg<TDbCol> pckg(aCol);
314 iColumns->Check(aColNo);
315 iObject.SendReceive(EDbsCursorColumnDef,TIpcArgs(aColNo,TIpcArgs::ENothing,TIpcArgs::ENothing,&pckg));
318 TDbColType CDbsCursor::ColumnType(TDbColNo aCol)
323 RDbRow* CDbsCursor::RowBuffer()
325 // Invoked by the server-- should not be called
332 TDbColumnC CDbsCursor::ColumnC(TDbColNo aCol)
334 // check row is valid for extraction
337 __ASSERT_ALWAYS(iState>=ERead,Panic(EDbsNoRowData));
338 return TDbColumnC(iRow,aCol);
341 TDbColumn CDbsCursor::Column(TDbColNo aCol)
343 // check row is valid for writing
346 __ASSERT_ALWAYS(iState==EWrite,Panic(EDbsNotInUpdate));
347 return TDbColumn(iRow,aCol);
350 void CDbsCursor::ReplaceBlobL(TDbColumn& aCol)
352 // We no longer know what the shape of a blob is, mark it as "unknown"
356 aCol.SetBlobL(KUnknownBlobId);
359 void CDbsCursor::SetNullL(TDbColNo aCol)
361 // Make the column Null
364 TDbColumn col=Column(aCol);
365 if (!TDbCol::IsLong(Type(aCol)))
367 else if (!TDbColumnC(col).IsNull())
370 iObject.SendReceiveL(EDbsCursorSetNull,TIpcArgs(aCol));
374 TInt CDbsCursor::ColumnSize(TDbColNo aCol)
376 TDbColumnC col(ColumnC(aCol));
377 if (!TDbCol::IsLong(Type(aCol)))
379 TInt size=col.Blob().Size();
382 // unknown size, so ask the server
383 return iObject.SendReceive(EDbsCursorColumnSize,TIpcArgs(aCol));
386 MStreamBuf* CDbsCursor::ColumnSourceL(TDbColNo aCol)
388 TDbColumnC col(ColumnC(aCol));
389 if (!TDbCol::IsLong(iColumns->Type(aCol)))
390 return HDbsReadBuf::NewL(col.PtrC8());
392 const TDbBlob& blob=col.Blob();
394 return HDbsReadBuf::NewL(blob.PtrC8());
395 // get it from the server
397 return HDbsBuf::NewL(iObject,EDbsCursorColumnSource,args);
400 MStreamBuf* CDbsCursor::ColumnSinkL(TDbColNo aCol)
402 TDbColumn col(Column(aCol));
405 return HDbsBuf::NewL(iObject,EDbsCursorColumnSink,args);
408 CDbRowConstraint* CDbsCursor::OpenConstraintL(const TDbQuery& aQuery)
410 const TDesC& des = aQuery.Query();
411 CDbsConstraint* c=new(ELeave) CDbsConstraint();
412 CleanupStack::PushL(c);
413 c->iObject.OpenL(iObject,EDbsCursorOpenConstraint,TIpcArgs(&des,aQuery.Comparison()));
418 TBool CDbsCursor::MatchL(CDbRowConstraint& aConstraint)
420 TInt handle = STATIC_CAST(CDbsConstraint&,aConstraint).iObject.Handle();
421 return iObject.SendReceiveL(EDbsCursorMatch,TIpcArgs(handle));
424 TInt CDbsCursor::FindL(RDbRowSet::TDirection aDirection,const TDbQuery& aCriteria)
426 // Server returns result-KErrNotFound, to ensure non-leaving on not found
429 const TDesC& des = aCriteria.Query();
431 TInt f=iObject.SendReceiveL(EDbsCursorFind,TIpcArgs(&des,aCriteria.Comparison(),aDirection))+KErrNotFound;
437 // Class CDbsConstraint
439 CDbsConstraint::~CDbsConstraint()