os/persistentdata/persistentstorage/dbms/utable/UT_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
//
sl@0
    15
sl@0
    16
#include "UT_STD.H"
sl@0
    17
sl@0
    18
// Class CDbTableCursor::HColumns
sl@0
    19
sl@0
    20
class CDbTableCursor::HColumns
sl@0
    21
	{
sl@0
    22
public:
sl@0
    23
	static HColumns* NewL(const CDbDataSource* aSource);
sl@0
    24
	inline TInt Count() const
sl@0
    25
		{return iCount;}
sl@0
    26
	inline TDbColType Type(TDbColNo aCol) const
sl@0
    27
		{__DEBUG(Check(aCol));return TDbColType(iType[aCol-1]);}
sl@0
    28
	void Check(TDbColNo aCol) const;
sl@0
    29
private:
sl@0
    30
	TInt iCount;
sl@0
    31
	TUint8 iType[1];
sl@0
    32
	};
sl@0
    33
sl@0
    34
CDbTableCursor::HColumns* CDbTableCursor::HColumns::NewL(const CDbDataSource* aSource)
sl@0
    35
	{
sl@0
    36
	TInt count=aSource->ColumnCount();
sl@0
    37
	HColumns* self=(HColumns*)User::AllocL(_FOFF(HColumns,iType[count]));
sl@0
    38
	self->iCount=count;
sl@0
    39
	TUint8* pp=&self->iType[0];
sl@0
    40
	for (TDbColNo ii=1;ii<=count;++ii,++pp)
sl@0
    41
		*pp=aSource->ColumnDef(ii).iType;
sl@0
    42
	return self;
sl@0
    43
	}
sl@0
    44
sl@0
    45
void CDbTableCursor::HColumns::Check(TDbColNo aColNo) const
sl@0
    46
	{
sl@0
    47
	__ASSERT_ALWAYS(TUint(aColNo-1)<TUint(iCount),Panic(EDbInvalidColumn));
sl@0
    48
	}
sl@0
    49
sl@0
    50
// Class CDbTableCursor::CConstraint
sl@0
    51
sl@0
    52
NONSHARABLE_CLASS(CDbTableCursor::CConstraint) : public CDbRowConstraint
sl@0
    53
	{
sl@0
    54
public:
sl@0
    55
	CConstraint(CDbTableCursor& aCursor,CSqlSearchCondition* aSearchCondition,TDbTextComparison aComparison);
sl@0
    56
	~CConstraint();
sl@0
    57
//
sl@0
    58
	inline TBool Check(CDbTableCursor& aCursor) const;
sl@0
    59
	inline TBool MatchL() const;
sl@0
    60
private:
sl@0
    61
	CDbTableCursor& iCursor;
sl@0
    62
	CSqlSearchCondition* iSearchCondition;
sl@0
    63
	const TTextOps& iTextOps;
sl@0
    64
	};
sl@0
    65
sl@0
    66
CDbTableCursor::CConstraint::CConstraint(CDbTableCursor& aCursor,CSqlSearchCondition* aSearchCondition,TDbTextComparison aComparison)
sl@0
    67
	: iCursor(aCursor), iSearchCondition(aSearchCondition), iTextOps(TTextOps::Ops(aComparison))
sl@0
    68
	{}
sl@0
    69
sl@0
    70
CDbTableCursor::CConstraint::~CConstraint()
sl@0
    71
	{
sl@0
    72
	delete iSearchCondition;
sl@0
    73
	}
sl@0
    74
sl@0
    75
inline TBool CDbTableCursor::CConstraint::Check(CDbTableCursor& aCursor) const
sl@0
    76
	{return &iCursor==&aCursor;}
sl@0
    77
inline TBool CDbTableCursor::CConstraint::MatchL() const
sl@0
    78
	{return iSearchCondition->EvaluateL(iTextOps);}
sl@0
    79
sl@0
    80
// Class CDbTableCursor
sl@0
    81
sl@0
    82
inline void CDbTableCursor::CheckStateL() const
sl@0
    83
	{iValid.CheckL();}
sl@0
    84
inline RDbTransaction& CDbTableCursor::Transaction()
sl@0
    85
	{__ASSERT(iValid);return iValid.Transaction();}
sl@0
    86
inline TBool CDbTableCursor::InUpdate() const
sl@0
    87
	{return iFlags&(EUpdating|EInserting);}
sl@0
    88
sl@0
    89
CDbTableCursor::CDbTableCursor(RDbAccessPlan& aPlan,RDbRowSet::TAccess aAccess)
sl@0
    90
	: iState(ERowBeginning),iValid(aPlan.Table()),iDataSource(aPlan.Adopt())
sl@0
    91
	{
sl@0
    92
	switch (aAccess)
sl@0
    93
		{
sl@0
    94
	default:
sl@0
    95
		__ASSERT(0);
sl@0
    96
	case RDbRowSet::EUpdatable:
sl@0
    97
		iFlags=EUpdatable|EReadable;
sl@0
    98
		break;
sl@0
    99
	case RDbRowSet::EReadOnly:
sl@0
   100
		iFlags=EReadable;
sl@0
   101
		break;
sl@0
   102
	case RDbRowSet::EInsertOnly:
sl@0
   103
		iFlags=EUpdatable;
sl@0
   104
		break;
sl@0
   105
		}
sl@0
   106
	}
sl@0
   107
sl@0
   108
CDbTableCursor::~CDbTableCursor()
sl@0
   109
	{
sl@0
   110
	Cancel();
sl@0
   111
	delete iDataSource;
sl@0
   112
	delete iColumns;
sl@0
   113
	}
sl@0
   114
sl@0
   115
CDbTableCursor* CDbTableCursor::NewL(RDbAccessPlan& aPlan,RDbRowSet::TAccess aAccess)
sl@0
   116
	{
sl@0
   117
	CDbTableCursor* self=new(ELeave) CDbTableCursor(aPlan,aAccess);
sl@0
   118
	CleanupStack::PushL(self);
sl@0
   119
	self->iColumns=HColumns::NewL(self->iDataSource);
sl@0
   120
	self->Reset();
sl@0
   121
	CleanupStack::Pop();
sl@0
   122
	return self;
sl@0
   123
	}
sl@0
   124
sl@0
   125
TDbColType CDbTableCursor::Type(TDbColNo aCol) const
sl@0
   126
	{
sl@0
   127
	iColumns->Check(aCol);
sl@0
   128
	return iColumns->Type(aCol);
sl@0
   129
	}
sl@0
   130
sl@0
   131
void CDbTableCursor::Reset()
sl@0
   132
//
sl@0
   133
// Reset the cursor for re-evaluation
sl@0
   134
//
sl@0
   135
	{
sl@0
   136
	AssertNotInUpdate();
sl@0
   137
	if (iValid.Reset())
sl@0
   138
		{
sl@0
   139
		iDataSource->Reset();
sl@0
   140
		iState=ERowBeginning;
sl@0
   141
		}
sl@0
   142
	}
sl@0
   143
sl@0
   144
TBool CDbTableCursor::EvaluateL()
sl@0
   145
//
sl@0
   146
// Do a unit of evaluation work
sl@0
   147
//
sl@0
   148
	{
sl@0
   149
	AssertNotInUpdate();
sl@0
   150
	CheckStateL();
sl@0
   151
	TInt work=256;
sl@0
   152
	TBool atRow=EFalse;
sl@0
   153
	TBool more=iDataSource->EvaluateL(work,iRecord,atRow);
sl@0
   154
	if (atRow)
sl@0
   155
		{	// evaluation results in a record appearing under the cursor
sl@0
   156
		switch (iState)
sl@0
   157
			{
sl@0
   158
		case ERowEnd:
sl@0
   159
		case ERowBeginning:
sl@0
   160
			iState=ERowOK;
sl@0
   161
			break;
sl@0
   162
		case ERowDeletedAtEnd:
sl@0
   163
			iState=ERowDeletedAtNext;
sl@0
   164
			break;
sl@0
   165
		default:
sl@0
   166
			break;
sl@0
   167
			}
sl@0
   168
		}
sl@0
   169
	return more?1:0;
sl@0
   170
	}
sl@0
   171
sl@0
   172
void CDbTableCursor::Evaluate(TRequestStatus& aStatus)
sl@0
   173
//
sl@0
   174
// Asynchronous evaluation: invoke synchronous version
sl@0
   175
//
sl@0
   176
	{
sl@0
   177
	TRequestStatus* pStatus=&aStatus;
sl@0
   178
	User::RequestComplete(pStatus,CDbCursor::Evaluate());
sl@0
   179
	}
sl@0
   180
sl@0
   181
TBool CDbTableCursor::Unevaluated()
sl@0
   182
//
sl@0
   183
// Report if there is evaluation to be done
sl@0
   184
//
sl@0
   185
	{
sl@0
   186
	return iValid ? iDataSource->Unevaluated() : EFalse;
sl@0
   187
	}
sl@0
   188
sl@0
   189
TInt CDbTableCursor::CountL(RDbRowSet::TAccuracy aAccuracy)
sl@0
   190
	{
sl@0
   191
	AssertNotInUpdate();
sl@0
   192
	CheckReadL();
sl@0
   193
	TInt count=iDataSource->CountL();
sl@0
   194
	return (count==KDbUndefinedCount && aAccuracy==RDbRowSet::EEnsure)
sl@0
   195
		? CDbCursor::CountL(aAccuracy)
sl@0
   196
		: count;
sl@0
   197
	}
sl@0
   198
sl@0
   199
TBool CDbTableCursor::AtBeginning()
sl@0
   200
	{
sl@0
   201
	return iState==ERowBeginning;
sl@0
   202
	}
sl@0
   203
sl@0
   204
TBool CDbTableCursor::AtEnd()
sl@0
   205
	{
sl@0
   206
	return iState==ERowEnd;
sl@0
   207
	}
sl@0
   208
sl@0
   209
TBool CDbTableCursor::AtRow()
sl@0
   210
	{
sl@0
   211
	return (iState==ERowOK||(iFlags&EInserting));
sl@0
   212
	}
sl@0
   213
sl@0
   214
TBool CDbTableCursor::GotoL(RDbRowSet::TPosition aPosition)
sl@0
   215
//
sl@0
   216
// Move the cursor in the requested direction
sl@0
   217
// return whether we are at a row or not
sl@0
   218
//
sl@0
   219
	{
sl@0
   220
	AssertNotInUpdate();
sl@0
   221
	CheckReadL();
sl@0
   222
	iFlags&=~ERead;
sl@0
   223
	switch (aPosition)
sl@0
   224
		{
sl@0
   225
	default:
sl@0
   226
		__ASSERT(0);
sl@0
   227
	case RDbRowSet::EFirst:
sl@0
   228
	case RDbRowSet::ELast:
sl@0
   229
		break;
sl@0
   230
	case RDbRowSet::ENext:
sl@0
   231
		switch (iState)
sl@0
   232
			{
sl@0
   233
		default:
sl@0
   234
			__ASSERT(0);
sl@0
   235
		case ERowInLimbo:	// in between previous and next, must evaluate
sl@0
   236
		case ERowOK:
sl@0
   237
			break;
sl@0
   238
		case ERowBeginning:		// goto first record
sl@0
   239
			aPosition=RDbRowSet::EFirst;
sl@0
   240
			break;
sl@0
   241
		case ERowEnd:
sl@0
   242
		case ERowInvalid:
sl@0
   243
			Panic(EDbInvalidRow);
sl@0
   244
			break;
sl@0
   245
		case ERowDeletedAtNext:	// already have the id
sl@0
   246
			if (iDataSource->GotoL(iRecord))
sl@0
   247
				{	// and the record is still there
sl@0
   248
				iState=ERowOK;
sl@0
   249
				return ETrue;
sl@0
   250
				}
sl@0
   251
			break;
sl@0
   252
		case ERowDeletedAtEnd:	// straight to end
sl@0
   253
			iState=ERowEnd;
sl@0
   254
			return EFalse;
sl@0
   255
			}
sl@0
   256
		break;
sl@0
   257
	case RDbRowSet::EPrevious:
sl@0
   258
		switch (iState)
sl@0
   259
			{
sl@0
   260
		default:
sl@0
   261
			__ASSERT(0);
sl@0
   262
		case ERowOK:
sl@0
   263
		case ERowDeletedAtNext:		// goto previous will do what we want
sl@0
   264
		case ERowInLimbo:	// in between previous and next, must evaluate
sl@0
   265
			break;
sl@0
   266
		case ERowEnd:				// goto last row
sl@0
   267
		case ERowDeletedAtEnd:		// previous is last row
sl@0
   268
			aPosition=RDbRowSet::ELast;
sl@0
   269
			break;
sl@0
   270
		case ERowBeginning:
sl@0
   271
		case ERowInvalid:
sl@0
   272
			Panic(EDbInvalidRow);
sl@0
   273
			break;
sl@0
   274
			}
sl@0
   275
		break;
sl@0
   276
	case RDbRowSet::EBeginning:
sl@0
   277
		iState=ERowBeginning;
sl@0
   278
		return EFalse;
sl@0
   279
	case RDbRowSet::EEnd:
sl@0
   280
		iState=ERowEnd;
sl@0
   281
		return EFalse;
sl@0
   282
		}
sl@0
   283
	iState=ERowInvalid;
sl@0
   284
	switch (iDataSource->GotoL(TDbPosition(aPosition),iRecord))
sl@0
   285
		{
sl@0
   286
	default:
sl@0
   287
		__ASSERT(0);
sl@0
   288
	case CDbDataSource::ESynchFailure:
sl@0
   289
		__LEAVE(KErrNotReady);
sl@0
   290
	case CDbDataSource::ESuccess:
sl@0
   291
		iState=ERowOK;
sl@0
   292
		return ETrue;
sl@0
   293
	case CDbDataSource::ENoRow:
sl@0
   294
		iState=TUint8(aPosition<RDbRowSet::EPrevious ? ERowEnd : ERowBeginning);
sl@0
   295
		return EFalse;
sl@0
   296
		}
sl@0
   297
	}
sl@0
   298
sl@0
   299
void CDbTableCursor::Bookmark(TDbBookmark::TMark& aMark)
sl@0
   300
//
sl@0
   301
// Create a bookmark for the current cursor state
sl@0
   302
// Can bookmark ANY position.
sl@0
   303
//
sl@0
   304
	{
sl@0
   305
	AssertNotInUpdate();
sl@0
   306
	aMark.iMark[0]=iState;
sl@0
   307
	aMark.iMark[1]=iRecord.Value();
sl@0
   308
	}
sl@0
   309
sl@0
   310
void CDbTableCursor::GotoL(const TDbBookmark::TMark& aMark)
sl@0
   311
//
sl@0
   312
// Reestablish the cursor state from a bookmark (if possible)
sl@0
   313
//
sl@0
   314
	{
sl@0
   315
	AssertNotInUpdate();
sl@0
   316
	CheckStateL();
sl@0
   317
	iState=ERowInvalid;
sl@0
   318
	iRecord=aMark.iMark[1];
sl@0
   319
	TState state=TState(aMark.iMark[0]);
sl@0
   320
	switch (state)
sl@0
   321
		{
sl@0
   322
	default:
sl@0
   323
		Panic(EDbInvalidBookmark);
sl@0
   324
	case ERowBeginning:
sl@0
   325
	case ERowEnd:
sl@0
   326
	case ERowDeletedAtEnd:
sl@0
   327
	case ERowInLimbo:
sl@0
   328
	case ERowInvalid:
sl@0
   329
		break;
sl@0
   330
	case ERowDeletedAtNext:
sl@0
   331
	case ERowOK:
sl@0
   332
		if (!iDataSource->GotoL(iRecord))
sl@0
   333
			__LEAVE(KErrNotFound);
sl@0
   334
		break;
sl@0
   335
		}
sl@0
   336
	iState=TUint8(state);
sl@0
   337
	}
sl@0
   338
sl@0
   339
void CDbTableCursor::GetL()
sl@0
   340
//
sl@0
   341
// read the current row into the row buffer for access
sl@0
   342
//
sl@0
   343
	{
sl@0
   344
	AssertValidRow();
sl@0
   345
	CheckStateL();
sl@0
   346
	iFlags&=~ERead;
sl@0
   347
	iDataSource->ReadRowL(iRecord);
sl@0
   348
	iFlags|=ERead;
sl@0
   349
	}
sl@0
   350
sl@0
   351
void CDbTableCursor::InsertL(TInsert aClearRow)
sl@0
   352
//
sl@0
   353
// Insert a new row. If aCLearRow==aCopy, then copy the current row
sl@0
   354
//
sl@0
   355
	{
sl@0
   356
	AssertNotInUpdate();
sl@0
   357
	CheckUpdateL();
sl@0
   358
	Transaction().DMLPrepareL(*this);
sl@0
   359
	if (aClearRow==ECopy)
sl@0
   360
		{
sl@0
   361
		AssertValidRow();
sl@0
   362
		iFlags&=~ERead;	// in case of failure in NewRowL
sl@0
   363
		iDataSource->NewRowL(iRecord);
sl@0
   364
		}
sl@0
   365
	else
sl@0
   366
		iDataSource->NewRowL(KDbNullRecordId);
sl@0
   367
	iFlags|=EInserting|ERead;
sl@0
   368
	Transaction().DMLBegin();
sl@0
   369
	}
sl@0
   370
sl@0
   371
void CDbTableCursor::UpdateL()
sl@0
   372
	{
sl@0
   373
	CheckUpdateL();
sl@0
   374
	Transaction().DMLPrepareL(*this);
sl@0
   375
	GetL();
sl@0
   376
	iFlags|=EUpdating;
sl@0
   377
	Transaction().DMLBegin();
sl@0
   378
	}
sl@0
   379
sl@0
   380
void CDbTableCursor::Cancel()
sl@0
   381
	{
sl@0
   382
	AssertNoStreams();
sl@0
   383
	if (InUpdate())
sl@0
   384
		{
sl@0
   385
		RDbTransaction& t=Transaction();
sl@0
   386
		if (iFlags&EDirty)
sl@0
   387
			t.DMLTouch();			// we've mucked about with BLOBs, so force true roll-back
sl@0
   388
		t.DMLRollback();
sl@0
   389
		if (iFlags&EUpdating)
sl@0
   390
			{
sl@0
   391
			TRAP_IGNORE(iDataSource->ReadRowL(KDbNullRecordId));	// row buffer contains NULL row	(cannot fail)
sl@0
   392
			}
sl@0
   393
		iFlags&=(EUpdatable|EReadable);
sl@0
   394
		}
sl@0
   395
	}
sl@0
   396
sl@0
   397
void CDbTableCursor::PutL()
sl@0
   398
	{
sl@0
   399
	AssertInUpdate();
sl@0
   400
	CheckStateL();
sl@0
   401
	CDbDataSource::TWrite mode=iFlags&EUpdating ? CDbDataSource::EReplace : CDbDataSource::EAppend;
sl@0
   402
	iDataSource->PrepareToWriteRowL(mode);
sl@0
   403
	RDbTransaction& t=Transaction();
sl@0
   404
	t.DMLTouch();
sl@0
   405
	iFlags&=~EDirty;
sl@0
   406
	iRecord=iDataSource->WriteRowL(mode,iFlags&EReadable ? CDbDataSource::ESynch : CDbDataSource::ENoSynch);
sl@0
   407
	t.DMLCommitL();
sl@0
   408
	if ((iFlags&(EInserting|EReadable))==(EInserting|EReadable))
sl@0
   409
		iState=ERowOK;
sl@0
   410
	iFlags&=(EUpdatable|EReadable|ERead);
sl@0
   411
	}
sl@0
   412
sl@0
   413
void CDbTableCursor::DeleteL()
sl@0
   414
	{
sl@0
   415
	AssertValidRow();
sl@0
   416
	CheckUpdateL();
sl@0
   417
	RDbTransaction& t=Transaction();
sl@0
   418
	t.DMLPrepareL(*this);
sl@0
   419
	t.DMLBeginLC();
sl@0
   420
	CDbDataSource::TDelete del=iDataSource->DeleteRowL(iRecord);
sl@0
   421
	t.DMLCommitL();
sl@0
   422
	CleanupStack::Pop();	// rollback not required
sl@0
   423
	iState=TUint8(del+ERowDeletedAtNext);
sl@0
   424
	}
sl@0
   425
sl@0
   426
TInt CDbTableCursor::ColumnCount()
sl@0
   427
	{
sl@0
   428
	return iColumns->Count();
sl@0
   429
	}
sl@0
   430
sl@0
   431
void CDbTableCursor::ColumnDef(TDbCol& aCol,TDbColNo aColNo)
sl@0
   432
	{
sl@0
   433
	iColumns->Check(aColNo);
sl@0
   434
	if (iValid)
sl@0
   435
		iDataSource->ColumnDef(aColNo).AsTDbCol(aCol);
sl@0
   436
	}
sl@0
   437
sl@0
   438
TDbColType CDbTableCursor::ColumnType(TDbColNo aCol)
sl@0
   439
	{
sl@0
   440
	return Type(aCol);
sl@0
   441
	}
sl@0
   442
sl@0
   443
void CDbTableCursor::ReplaceBlobL(TDbColumn& aCol)
sl@0
   444
	{
sl@0
   445
	CheckStateL();
sl@0
   446
	const TDbBlob& blob=TDbColumnC(aCol).Blob();
sl@0
   447
	if (!blob.IsInline())
sl@0
   448
		{
sl@0
   449
		iFlags|=EDirty;
sl@0
   450
		BlobsL().DeleteL(blob.Id());
sl@0
   451
		}
sl@0
   452
	}
sl@0
   453
sl@0
   454
void CDbTableCursor::AddBlobSource()
sl@0
   455
//
sl@0
   456
// Increment the source count and take a read-lock on the database
sl@0
   457
//
sl@0
   458
	{
sl@0
   459
	AddSource();
sl@0
   460
	Transaction().ReadBegin(*this);
sl@0
   461
	}
sl@0
   462
sl@0
   463
void CDbTableCursor::ReleaseBlobSource()
sl@0
   464
//
sl@0
   465
// Decrement the source count and release the read-lock on the database
sl@0
   466
//
sl@0
   467
	{
sl@0
   468
	ReleaseSource();
sl@0
   469
	Transaction().ReadRelease(*this);
sl@0
   470
	}
sl@0
   471
sl@0
   472
MStreamBuf* CDbTableCursor::ColumnSourceL(TDbColNo aCol)
sl@0
   473
	{
sl@0
   474
	TDbColumnC col(ColumnC(aCol));
sl@0
   475
	if ((iFlags&EWriteBuf) || iReadBuf==EMaxReadBuf)
sl@0
   476
		__LEAVE(KErrInUse);			// only allow 1-write or 255-read streambufs
sl@0
   477
	TDbColType type=iColumns->Type(aCol);
sl@0
   478
	if (!TDbCol::IsLong(type))
sl@0
   479
		return HMemBuf::NewL(*this,col.PtrC8());
sl@0
   480
	// blobs
sl@0
   481
	const TDbBlob& blob=col.Blob();
sl@0
   482
	if (blob.IsInline())
sl@0
   483
		return HMemBuf::NewL(*this,blob.PtrC8());
sl@0
   484
	// if small enough, pull the blob data through immediately and avoid locking the database
sl@0
   485
	if (blob.Size()<=HHeapBuf::EMaxBlobBuffer)
sl@0
   486
		return HHeapBuf::NewL(*this,blob,type);
sl@0
   487
	//
sl@0
   488
	CheckStateL();
sl@0
   489
	Transaction().ReadPrepareL(*this);
sl@0
   490
	HReadBuf* buf=HReadBuf::NewLC(*this);
sl@0
   491
	buf->Set(BlobsL().ReadL(blob.Id(),type));
sl@0
   492
	CleanupStack::Pop();
sl@0
   493
	return buf;
sl@0
   494
	}
sl@0
   495
sl@0
   496
MStreamBuf* CDbTableCursor::ColumnSinkL(TDbColNo aCol)
sl@0
   497
	{
sl@0
   498
	TDbColType type=Type(aCol);
sl@0
   499
	__ASSERT_ALWAYS(TDbCol::IsLong(type),Panic(EDbWrongType));
sl@0
   500
	TDbColumn col=Column(aCol);
sl@0
   501
	ReplaceBlobL(col);
sl@0
   502
	iFlags|=EDirty;
sl@0
   503
	return HWriteBuf::NewL(*this,col,type);
sl@0
   504
	}
sl@0
   505
sl@0
   506
void CDbTableCursor::SetNullL(TDbColNo aCol)
sl@0
   507
//
sl@0
   508
// Make the column Null
sl@0
   509
//
sl@0
   510
	{
sl@0
   511
	TDbColumn col=Column(aCol);
sl@0
   512
	if (TDbCol::IsLong(Type(aCol)))
sl@0
   513
		ReplaceBlobL(col);
sl@0
   514
	col.SetNull();
sl@0
   515
	}
sl@0
   516
sl@0
   517
TInt CDbTableCursor::ColumnSize(TDbColNo aCol)
sl@0
   518
	{
sl@0
   519
	TDbColumnC col(ColumnC(aCol));
sl@0
   520
	return TDbCol::IsLong(Type(aCol)) ? col.Blob().Size() : col.Size();
sl@0
   521
	}
sl@0
   522
sl@0
   523
RDbRow* CDbTableCursor::RowBuffer()
sl@0
   524
//
sl@0
   525
// Invoked by the server for whole-row access where possible
sl@0
   526
//
sl@0
   527
	{
sl@0
   528
	__ASSERT(iFlags&ERead);
sl@0
   529
	return iDataSource->RowBuffer();
sl@0
   530
	}
sl@0
   531
sl@0
   532
TDbColumnC CDbTableCursor::ColumnC(TDbColNo aCol)
sl@0
   533
//
sl@0
   534
// check row is valid for extraction
sl@0
   535
//
sl@0
   536
	{
sl@0
   537
	__ASSERT_ALWAYS(iFlags&ERead,Panic(EDbRowNotRead));
sl@0
   538
	return iDataSource->Column(aCol);
sl@0
   539
	}
sl@0
   540
sl@0
   541
TDbColumn CDbTableCursor::Column(TDbColNo aCol)
sl@0
   542
//
sl@0
   543
// check row is valid for writing
sl@0
   544
//
sl@0
   545
	{
sl@0
   546
	AssertInUpdate();
sl@0
   547
	return iDataSource->Column(aCol);
sl@0
   548
	}
sl@0
   549
sl@0
   550
void CDbTableCursor::SetIndexL(const TDesC* anIndex)
sl@0
   551
	{
sl@0
   552
	AssertNotInUpdate();
sl@0
   553
	CheckReadL();
sl@0
   554
	iDataSource->SetIndexL(anIndex);
sl@0
   555
	iState=ERowBeginning;
sl@0
   556
	}
sl@0
   557
sl@0
   558
TBool CDbTableCursor::SeekL(const TDbLookupKey& aKey,RDbTable::TComparison aComparison)
sl@0
   559
	{
sl@0
   560
	AssertNotInUpdate();
sl@0
   561
	CheckReadL();
sl@0
   562
	iFlags&=~ERead;
sl@0
   563
	iState=ERowInvalid;
sl@0
   564
	TBool atrow=iDataSource->SeekL(aKey,aComparison,iRecord);
sl@0
   565
	if (atrow)
sl@0
   566
		iState=ERowOK;
sl@0
   567
	return atrow;
sl@0
   568
	}
sl@0
   569
sl@0
   570
CDbRowConstraint* CDbTableCursor::OpenConstraintL(const TDbQuery& aCriteria)
sl@0
   571
//
sl@0
   572
// Construct a constraint for this rowset
sl@0
   573
//
sl@0
   574
	{
sl@0
   575
	CSqlSearchCondition* sc=iDataSource->ParseConstraintLC(aCriteria.Query());
sl@0
   576
	CDbRowConstraint* constraint=new(ELeave) CConstraint(*this,sc,aCriteria.Comparison());
sl@0
   577
	CleanupStack::Pop();
sl@0
   578
	return constraint;
sl@0
   579
	}
sl@0
   580
sl@0
   581
TBool CDbTableCursor::MatchL(CDbRowConstraint& aConstraint)
sl@0
   582
	{
sl@0
   583
	CConstraint& c=STATIC_CAST(CConstraint&,aConstraint);
sl@0
   584
	__ASSERT_ALWAYS(c.Check(*this),Panic(EDbRowSetConstraintMismatch));
sl@0
   585
	GetL();
sl@0
   586
	return c.MatchL();
sl@0
   587
	}
sl@0
   588
sl@0
   589
void CDbTableCursor::CheckReadL() const
sl@0
   590
//
sl@0
   591
// Ensure we are a readable cursor
sl@0
   592
//
sl@0
   593
	{
sl@0
   594
	CheckStateL();
sl@0
   595
	if ((iFlags&EReadable)==0)
sl@0
   596
		__LEAVE(KErrWrite);
sl@0
   597
	}
sl@0
   598
sl@0
   599
void CDbTableCursor::CheckUpdateL() const
sl@0
   600
//
sl@0
   601
// Ensure we are a writable cursor
sl@0
   602
//
sl@0
   603
	{
sl@0
   604
	CheckStateL();
sl@0
   605
	if ((iFlags&EUpdatable)==0)
sl@0
   606
		__LEAVE(KErrWrite);
sl@0
   607
	}
sl@0
   608
sl@0
   609
void CDbTableCursor::AssertNoStreams() const
sl@0
   610
	{
sl@0
   611
	__ASSERT_ALWAYS((iFlags&EWriteBuf)==0 && iReadBuf==0,Panic(EDbStreamOpen));
sl@0
   612
	}
sl@0
   613
sl@0
   614
void CDbTableCursor::AssertNotInUpdate() const
sl@0
   615
	{
sl@0
   616
	__ASSERT_ALWAYS(!InUpdate(),Panic(EDbInUpdate));
sl@0
   617
	AssertNoStreams();
sl@0
   618
	}
sl@0
   619
sl@0
   620
void CDbTableCursor::AssertInUpdate() const
sl@0
   621
	{
sl@0
   622
	__ASSERT_ALWAYS(InUpdate(),Panic(EDbNotInUpdate));
sl@0
   623
	AssertNoStreams();
sl@0
   624
	}
sl@0
   625
sl@0
   626
void CDbTableCursor::AssertValidRow() const
sl@0
   627
	{
sl@0
   628
	AssertNotInUpdate();
sl@0
   629
	__ASSERT_ALWAYS(iState==ERowOK||(iFlags&EInserting),Panic(EDbInvalidRow));
sl@0
   630
	}
sl@0
   631