os/persistentdata/persistentstorage/dbms/sdbms/SD_CURS.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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
// DBMS server proxy cursor
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "SD_STD.H"
sl@0
    19
sl@0
    20
const TDbBlobId KUnknownBlobId=~0u;
sl@0
    21
sl@0
    22
// Class HDbsColumns
sl@0
    23
sl@0
    24
class HDbsColumns
sl@0
    25
	{
sl@0
    26
public:
sl@0
    27
	static HDbsColumns* NewL(TInt aCount);
sl@0
    28
	inline void Set(const TUint8* aPtr);
sl@0
    29
	inline TPtr8 Ptr();
sl@0
    30
	inline TInt Count() const;
sl@0
    31
	inline TDbColType Type(TDbColNo aCol) const;
sl@0
    32
	void Check(TDbColNo aCol) const;
sl@0
    33
private:
sl@0
    34
	inline HDbsColumns(TInt aCount);
sl@0
    35
private:
sl@0
    36
	TInt iCount;
sl@0
    37
	TUint8 iType[1];
sl@0
    38
	};
sl@0
    39
sl@0
    40
inline HDbsColumns::HDbsColumns(TInt aCount)
sl@0
    41
	:iCount(aCount)
sl@0
    42
	{}
sl@0
    43
inline void HDbsColumns::Set(const TUint8* aPtr)
sl@0
    44
	{Mem::Copy(iType,aPtr,iCount);}
sl@0
    45
inline TPtr8 HDbsColumns::Ptr()
sl@0
    46
	{return TPtr8(iType,iCount);}
sl@0
    47
inline TInt HDbsColumns::Count() const
sl@0
    48
	{return iCount;}
sl@0
    49
inline TDbColType HDbsColumns::Type(TDbColNo aCol) const
sl@0
    50
	{__DEBUG(Check(aCol));return TDbColType(iType[aCol-1]);}
sl@0
    51
sl@0
    52
HDbsColumns* HDbsColumns::NewL(TInt aCount)
sl@0
    53
	{
sl@0
    54
	return new(User::AllocL(_FOFF(HDbsColumns,iType[aCount]))) HDbsColumns(aCount);
sl@0
    55
	}
sl@0
    56
sl@0
    57
void HDbsColumns::Check(TDbColNo aColNo) const
sl@0
    58
	{
sl@0
    59
	__ASSERT_ALWAYS(aColNo>0&&aColNo<=iCount,Panic(EDbsInvalidColumn));
sl@0
    60
	}
sl@0
    61
sl@0
    62
// Class CDbsCursor
sl@0
    63
sl@0
    64
CDbsCursor::CDbsCursor()
sl@0
    65
	:iState(EAtBeginning)
sl@0
    66
	{}
sl@0
    67
sl@0
    68
CDbsCursor* CDbsCursor::NewL(const RDbsObject& aDbs,TDbsFunction aFunction,TIpcArgs& aArgs)
sl@0
    69
	{
sl@0
    70
	CDbsCursor* self=new(ELeave) CDbsCursor;
sl@0
    71
	CleanupStack::PushL(self);
sl@0
    72
	self->ConstructL(aDbs,aFunction,aArgs);
sl@0
    73
	CleanupStack::Pop();
sl@0
    74
	return self;
sl@0
    75
	}
sl@0
    76
sl@0
    77
void CDbsCursor::ConstructL(const RDbsObject& aDbs,TDbsFunction aFunction,TIpcArgs& aArgs)
sl@0
    78
//
sl@0
    79
// construct a cursor from the supplied parameters
sl@0
    80
// Retrieve the column types, in one pass if possible
sl@0
    81
//
sl@0
    82
	{
sl@0
    83
	TPckgBuf<TDbsColumns> cols;
sl@0
    84
	aArgs.Set(3,&cols);
sl@0
    85
	iObject.OpenL(aDbs,aFunction,aArgs);
sl@0
    86
	iColumns=HDbsColumns::NewL(cols().iCount);
sl@0
    87
	if (cols().iCount<=cols().EMax)
sl@0
    88
		iColumns->Set(cols().iData);	// we have the column types
sl@0
    89
	else
sl@0
    90
		{	// too many for the fixed buffer, make a second call to get the columns
sl@0
    91
		TPtr8 ptr=iColumns->Ptr();
sl@0
    92
		aArgs.Set(3,&ptr);
sl@0
    93
		iObject.SendReceiveL(EDbsCursorColumnTypes,aArgs);
sl@0
    94
		}
sl@0
    95
	}
sl@0
    96
sl@0
    97
CDbsCursor::~CDbsCursor()
sl@0
    98
	{
sl@0
    99
	iObject.Close();
sl@0
   100
	delete iColumns;
sl@0
   101
	iRow.Close();
sl@0
   102
	}
sl@0
   103
sl@0
   104
TDbColType CDbsCursor::Type(TDbColNo aCol) const
sl@0
   105
	{
sl@0
   106
	iColumns->Check(aCol);
sl@0
   107
	return iColumns->Type(aCol);
sl@0
   108
	}
sl@0
   109
sl@0
   110
void CDbsCursor::Reset()
sl@0
   111
	{
sl@0
   112
	iState=EAtBeginning;
sl@0
   113
	iObject.SendReceive(EDbsCursorReset);
sl@0
   114
	}
sl@0
   115
sl@0
   116
TBool CDbsCursor::EvaluateL()
sl@0
   117
	{
sl@0
   118
	iState=EUnknown;
sl@0
   119
	return iObject.SendReceiveL(EDbsCursorEvaluate);
sl@0
   120
	}
sl@0
   121
sl@0
   122
void CDbsCursor::Evaluate(TRequestStatus& aStatus)
sl@0
   123
	{
sl@0
   124
	iState=EUnknown;
sl@0
   125
	iObject.SendReceive(EDbsCursorEvaluate,aStatus);
sl@0
   126
	}
sl@0
   127
sl@0
   128
TBool CDbsCursor::Unevaluated()
sl@0
   129
	{
sl@0
   130
	return iObject.SendReceive(EDbsCursorUnevaluated);
sl@0
   131
	}
sl@0
   132
sl@0
   133
void CDbsCursor::SetIndexL(const TDesC* anIndex)
sl@0
   134
	{
sl@0
   135
	iObject.SendReceiveL(EDbsCursorSetIndex,TIpcArgs(anIndex));
sl@0
   136
	iState=EAtBeginning;
sl@0
   137
	}
sl@0
   138
sl@0
   139
TBool CDbsCursor::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison)
sl@0
   140
	{
sl@0
   141
	TPtrC8 key(TDbsParam::PrepareLC(aKey));
sl@0
   142
	iState=EUnknown;
sl@0
   143
	TBool found=iObject.SendReceiveL(EDbsCursorSeek,TIpcArgs(&key,key.Length(),aComparison));
sl@0
   144
	CleanupStack::PopAndDestroy();	// key
sl@0
   145
	if (found)
sl@0
   146
		iState=EAtRow;
sl@0
   147
	return found;
sl@0
   148
	}
sl@0
   149
sl@0
   150
TBool CDbsCursor::AtBeginning()
sl@0
   151
	{
sl@0
   152
	if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtBeginning)>0)
sl@0
   153
		iState=EAtBeginning;
sl@0
   154
	return iState==EAtBeginning;
sl@0
   155
	}
sl@0
   156
sl@0
   157
TBool CDbsCursor::AtEnd()
sl@0
   158
	{
sl@0
   159
	if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtEnd)>0)
sl@0
   160
		iState=EAtEnd;
sl@0
   161
	return iState==EAtEnd;
sl@0
   162
	}
sl@0
   163
sl@0
   164
TBool CDbsCursor::AtRow()
sl@0
   165
	{
sl@0
   166
	if (iState==EUnknown && iObject.SendReceive(EDbsCursorAtRow)>0)
sl@0
   167
		iState=EAtRow;
sl@0
   168
	return iState>=EAtRow;
sl@0
   169
	}
sl@0
   170
sl@0
   171
TInt CDbsCursor::CountL(RDbRowSet::TAccuracy aAccuracy)
sl@0
   172
//
sl@0
   173
// valid response is >=0 + undefined (==-1)
sl@0
   174
// server returns +1 for non-error conditions
sl@0
   175
//
sl@0
   176
	{
sl@0
   177
	return iObject.SendReceiveL(EDbsCursorCount,TIpcArgs(aAccuracy))-1;
sl@0
   178
	}
sl@0
   179
sl@0
   180
TBool CDbsCursor::GotoL(RDbRowSet::TPosition aPosition)
sl@0
   181
	{
sl@0
   182
	TBool atrow=RetrieveL(EDbsCursorGotoPos,aPosition);
sl@0
   183
	if (atrow)
sl@0
   184
		iState=ERetrieve;
sl@0
   185
	else
sl@0
   186
		{
sl@0
   187
		switch (aPosition)
sl@0
   188
			{
sl@0
   189
		default:
sl@0
   190
			__ASSERT(0);
sl@0
   191
		case RDbRowSet::EEnd:
sl@0
   192
		case RDbRowSet::EFirst:
sl@0
   193
		case RDbRowSet::ENext:
sl@0
   194
			iState=EAtEnd;
sl@0
   195
			break;
sl@0
   196
		case RDbRowSet::EBeginning:
sl@0
   197
		case RDbRowSet::ELast:
sl@0
   198
		case RDbRowSet::EPrevious:
sl@0
   199
			iState=EAtBeginning;
sl@0
   200
			break;
sl@0
   201
			}
sl@0
   202
		}
sl@0
   203
	return atrow;
sl@0
   204
	}
sl@0
   205
sl@0
   206
void CDbsCursor::Bookmark(TDbBookmark::TMark& aMark)
sl@0
   207
	{
sl@0
   208
	TPckg<TDbBookmark::TMark> pckg(aMark);
sl@0
   209
	iObject.SendReceive(EDbsCursorBookmark,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,&pckg));
sl@0
   210
	}
sl@0
   211
sl@0
   212
void CDbsCursor::GotoL(const TDbBookmark::TMark& aMark)
sl@0
   213
	{
sl@0
   214
	TPckgC<TDbBookmark::TMark> pckg(aMark);
sl@0
   215
	iState=EUnknown;
sl@0
   216
	iObject.SendReceiveL(EDbsCursorGotoBookmark,TIpcArgs(&pckg));
sl@0
   217
	}
sl@0
   218
sl@0
   219
LOCAL_C void CancelCursor(TAny* aPtr)
sl@0
   220
	{
sl@0
   221
	STATIC_CAST(CDbCursor*,aPtr)->Cancel();
sl@0
   222
	}
sl@0
   223
sl@0
   224
TBool CDbsCursor::RetrieveL(TDbsFunction aFunction,TInt aArg0)
sl@0
   225
//
sl@0
   226
// Read the row buffer
sl@0
   227
//
sl@0
   228
	{
sl@0
   229
	iState=EUnknown;
sl@0
   230
	TInt size;
sl@0
   231
	for (;;)
sl@0
   232
		{
sl@0
   233
		TInt max=iRow.MaxSize();
sl@0
   234
		TPtr8 row((TUint8*)iRow.First(),max);
sl@0
   235
		size=iObject.SendReceiveL(aFunction,TIpcArgs(aArg0,TIpcArgs::ENothing,max,&row))-1;
sl@0
   236
		if (size<0)
sl@0
   237
			return EFalse;		// no row to retrieve
sl@0
   238
		if (size<=max)
sl@0
   239
			break;
sl@0
   240
		// didn't fit! Grow the buffer
sl@0
   241
		if (aFunction!=EDbsCursorRetrieveRow)
sl@0
   242
			{
sl@0
   243
			CleanupStack::PushL(TCleanupItem(CancelCursor,this));	// in case this goes wrong!
sl@0
   244
			aFunction=EDbsCursorRetrieveRow;
sl@0
   245
			}
sl@0
   246
		iRow.GrowL(size);
sl@0
   247
		}
sl@0
   248
	iRow.SetSize(size);
sl@0
   249
	if (aFunction==EDbsCursorRetrieveRow)
sl@0
   250
		CleanupStack::Pop();
sl@0
   251
	return ETrue;
sl@0
   252
	}
sl@0
   253
sl@0
   254
void CDbsCursor::GetL()
sl@0
   255
	{
sl@0
   256
	if (iState!=ERetrieve)
sl@0
   257
		RetrieveL(EDbsCursorGet);
sl@0
   258
	iState=ERead;
sl@0
   259
	}
sl@0
   260
sl@0
   261
void CDbsCursor::InsertL(TInsert aClearRow)
sl@0
   262
	{
sl@0
   263
	RetrieveL(EDbsCursorInsert,aClearRow);
sl@0
   264
	iState=EWrite;
sl@0
   265
	iChangedBlob=EFalse;
sl@0
   266
	}
sl@0
   267
sl@0
   268
void CDbsCursor::UpdateL()
sl@0
   269
	{
sl@0
   270
	RetrieveL(EDbsCursorUpdate);
sl@0
   271
	iState=EWrite;
sl@0
   272
	iChangedBlob=EFalse;
sl@0
   273
	}
sl@0
   274
sl@0
   275
void CDbsCursor::Cancel()
sl@0
   276
	{
sl@0
   277
	if (iState==EUnknown || iState==EWrite)
sl@0
   278
		iObject.SendReceive(EDbsCursorCancel);
sl@0
   279
	}
sl@0
   280
sl@0
   281
void CDbsCursor::PutL()
sl@0
   282
	{
sl@0
   283
	TInt size=iRow.Size();
sl@0
   284
	TPtrC8 row((const TUint8*)iRow.First(),size);
sl@0
   285
	iObject.SendReceiveL(EDbsCursorPut,TIpcArgs(&row,size,iChangedBlob));// if iChangedBlob false, server can optimize put
sl@0
   286
	iState=ERead;		// we can still look at the row we put
sl@0
   287
	}
sl@0
   288
sl@0
   289
void CDbsCursor::DeleteL()
sl@0
   290
	{
sl@0
   291
	iState=EUnknown;
sl@0
   292
	iObject.SendReceiveL(EDbsCursorDelete);
sl@0
   293
	}
sl@0
   294
sl@0
   295
TInt CDbsCursor::ColumnCount()
sl@0
   296
	{
sl@0
   297
	return iColumns->Count();
sl@0
   298
	}
sl@0
   299
sl@0
   300
void CDbsCursor::ColumnsL(CDbColSet& aColSet)
sl@0
   301
//
sl@0
   302
// optimise the retreival of all columns
sl@0
   303
//
sl@0
   304
	{
sl@0
   305
	TIpcArgs m;
sl@0
   306
	RReadStream in(HDbsBuf::NewLC(iObject,EDbsCursorColumns,m));
sl@0
   307
	in>>aColSet;
sl@0
   308
	CleanupStack::PopAndDestroy();	// buffer
sl@0
   309
	}
sl@0
   310
sl@0
   311
void CDbsCursor::ColumnDef(TDbCol& aCol,TDbColNo aColNo)
sl@0
   312
	{
sl@0
   313
	TPckg<TDbCol> pckg(aCol);
sl@0
   314
	iColumns->Check(aColNo);
sl@0
   315
	iObject.SendReceive(EDbsCursorColumnDef,TIpcArgs(aColNo,TIpcArgs::ENothing,TIpcArgs::ENothing,&pckg));
sl@0
   316
	}
sl@0
   317
sl@0
   318
TDbColType CDbsCursor::ColumnType(TDbColNo aCol)
sl@0
   319
	{
sl@0
   320
	return Type(aCol);
sl@0
   321
	}
sl@0
   322
sl@0
   323
RDbRow* CDbsCursor::RowBuffer()
sl@0
   324
//
sl@0
   325
// Invoked by the server-- should not be called
sl@0
   326
//
sl@0
   327
	{
sl@0
   328
	__ASSERT(0);
sl@0
   329
	return 0;
sl@0
   330
	}
sl@0
   331
sl@0
   332
TDbColumnC CDbsCursor::ColumnC(TDbColNo aCol)
sl@0
   333
//
sl@0
   334
// check row is valid for extraction
sl@0
   335
//
sl@0
   336
	{
sl@0
   337
	__ASSERT_ALWAYS(iState>=ERead,Panic(EDbsNoRowData));
sl@0
   338
	return TDbColumnC(iRow,aCol);
sl@0
   339
	}
sl@0
   340
sl@0
   341
TDbColumn CDbsCursor::Column(TDbColNo aCol)
sl@0
   342
//
sl@0
   343
// check row is valid for writing
sl@0
   344
//
sl@0
   345
	{
sl@0
   346
	__ASSERT_ALWAYS(iState==EWrite,Panic(EDbsNotInUpdate));
sl@0
   347
	return TDbColumn(iRow,aCol);
sl@0
   348
	}
sl@0
   349
sl@0
   350
void CDbsCursor::ReplaceBlobL(TDbColumn& aCol)
sl@0
   351
//
sl@0
   352
// We no longer know what the shape of a blob is, mark it as "unknown"
sl@0
   353
//
sl@0
   354
	{
sl@0
   355
	iChangedBlob=ETrue;
sl@0
   356
	aCol.SetBlobL(KUnknownBlobId);
sl@0
   357
	}
sl@0
   358
sl@0
   359
void CDbsCursor::SetNullL(TDbColNo aCol)
sl@0
   360
//
sl@0
   361
// Make the column Null
sl@0
   362
//
sl@0
   363
	{
sl@0
   364
	TDbColumn col=Column(aCol);
sl@0
   365
	if (!TDbCol::IsLong(Type(aCol)))
sl@0
   366
		col.SetNull();
sl@0
   367
	else if (!TDbColumnC(col).IsNull())
sl@0
   368
		{
sl@0
   369
		ReplaceBlobL(col);
sl@0
   370
		iObject.SendReceiveL(EDbsCursorSetNull,TIpcArgs(aCol));
sl@0
   371
		}
sl@0
   372
	}
sl@0
   373
sl@0
   374
TInt CDbsCursor::ColumnSize(TDbColNo aCol)
sl@0
   375
	{
sl@0
   376
	TDbColumnC col(ColumnC(aCol));
sl@0
   377
	if (!TDbCol::IsLong(Type(aCol)))
sl@0
   378
		return col.Size();
sl@0
   379
	TInt size=col.Blob().Size();
sl@0
   380
	if (size>=0)
sl@0
   381
		return size;
sl@0
   382
	// unknown size, so ask the server
sl@0
   383
	return iObject.SendReceive(EDbsCursorColumnSize,TIpcArgs(aCol));
sl@0
   384
	}
sl@0
   385
sl@0
   386
MStreamBuf* CDbsCursor::ColumnSourceL(TDbColNo aCol)
sl@0
   387
	{
sl@0
   388
	TDbColumnC col(ColumnC(aCol));
sl@0
   389
	if (!TDbCol::IsLong(iColumns->Type(aCol)))
sl@0
   390
		return HDbsReadBuf::NewL(col.PtrC8());
sl@0
   391
	// blobs
sl@0
   392
	const TDbBlob& blob=col.Blob();
sl@0
   393
	if (blob.IsInline())
sl@0
   394
		return HDbsReadBuf::NewL(blob.PtrC8());
sl@0
   395
	// get it from the server
sl@0
   396
	TIpcArgs args(aCol);
sl@0
   397
	return HDbsBuf::NewL(iObject,EDbsCursorColumnSource,args);
sl@0
   398
	}
sl@0
   399
sl@0
   400
MStreamBuf* CDbsCursor::ColumnSinkL(TDbColNo aCol)
sl@0
   401
	{
sl@0
   402
	TDbColumn col(Column(aCol));
sl@0
   403
	ReplaceBlobL(col);
sl@0
   404
	TIpcArgs args(aCol);
sl@0
   405
	return HDbsBuf::NewL(iObject,EDbsCursorColumnSink,args);
sl@0
   406
	}
sl@0
   407
sl@0
   408
CDbRowConstraint* CDbsCursor::OpenConstraintL(const TDbQuery& aQuery)
sl@0
   409
	{
sl@0
   410
	const TDesC& des = aQuery.Query();
sl@0
   411
	CDbsConstraint* c=new(ELeave) CDbsConstraint();
sl@0
   412
	CleanupStack::PushL(c);
sl@0
   413
	c->iObject.OpenL(iObject,EDbsCursorOpenConstraint,TIpcArgs(&des,aQuery.Comparison()));
sl@0
   414
	CleanupStack::Pop();
sl@0
   415
	return c;
sl@0
   416
	}
sl@0
   417
sl@0
   418
TBool CDbsCursor::MatchL(CDbRowConstraint& aConstraint)
sl@0
   419
	{
sl@0
   420
	TInt handle = STATIC_CAST(CDbsConstraint&,aConstraint).iObject.Handle();
sl@0
   421
	return iObject.SendReceiveL(EDbsCursorMatch,TIpcArgs(handle));
sl@0
   422
	}
sl@0
   423
sl@0
   424
TInt CDbsCursor::FindL(RDbRowSet::TDirection aDirection,const TDbQuery& aCriteria)
sl@0
   425
//
sl@0
   426
// Server returns result-KErrNotFound, to ensure non-leaving on not found
sl@0
   427
//
sl@0
   428
	{
sl@0
   429
	const TDesC& des = aCriteria.Query();
sl@0
   430
	iState=EUnknown;
sl@0
   431
	TInt f=iObject.SendReceiveL(EDbsCursorFind,TIpcArgs(&des,aCriteria.Comparison(),aDirection))+KErrNotFound;
sl@0
   432
	if (f>=0)
sl@0
   433
		iState=EAtRow;
sl@0
   434
	return f;
sl@0
   435
	}
sl@0
   436
sl@0
   437
// Class CDbsConstraint
sl@0
   438
sl@0
   439
CDbsConstraint::~CDbsConstraint()
sl@0
   440
	{
sl@0
   441
	iObject.Close();
sl@0
   442
	}