os/persistentdata/persistentstorage/dbms/ustor/US_TABLE.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
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 "US_STD.H"
sl@0
    17
sl@0
    18
//#define __READBIT_CLASS
sl@0
    19
//#define __WRITEBIT_CLASS
sl@0
    20
sl@0
    21
#ifdef __READBIT_CLASS
sl@0
    22
class TReadBitSequence
sl@0
    23
	{
sl@0
    24
public:
sl@0
    25
	inline TReadBitSequence();
sl@0
    26
	inline TBool HasBits() const;
sl@0
    27
	TUint Read(const TUint8*& aPtr);
sl@0
    28
private:
sl@0
    29
	TUint iBits;
sl@0
    30
	};
sl@0
    31
inline TReadBitSequence::TReadBitSequence()
sl@0
    32
	:iBits(0) {}
sl@0
    33
inline TBool TReadBitSequence::HasBits() const
sl@0
    34
	{return (iBits&0x2000000);}
sl@0
    35
TUint TReadBitSequence::Read(const TUint8*& aPtr)
sl@0
    36
	{
sl@0
    37
	iBits>>=1;
sl@0
    38
	if ((iBits&0x1000000)==0)
sl@0
    39
		iBits=*aPtr++ | 0xff000000u;
sl@0
    40
	return iBits&1;
sl@0
    41
	}
sl@0
    42
#define READBITINIT(This) TReadBitSequence This
sl@0
    43
#define READHASBITS(This) This.HasBits()
sl@0
    44
#define READBIT(This,ptr) This.Read(ptr)
sl@0
    45
#define SKIPBIT(This,ptr) READBIT(This,ptr)
sl@0
    46
#else
sl@0
    47
#define READBITINIT(This) TUint This##_bits=0
sl@0
    48
#define READHASBITS(This) (This##_bits&0x2000000)
sl@0
    49
#define SKIPBIT(This,ptr) (This##_bits>>=1,(This##_bits&0x1000000 ? void(0) : void(This##_bits=*ptr++|0xff000000u)))
sl@0
    50
#define READBIT(This,ptr) (SKIPBIT(This,ptr),This##_bits&1)
sl@0
    51
#endif
sl@0
    52
sl@0
    53
#ifdef __WRITEBIT_CLASS
sl@0
    54
class TWriteBitSequence
sl@0
    55
	{
sl@0
    56
public:
sl@0
    57
	inline TWriteBitSequence();
sl@0
    58
	TUint8* Write(TUint8* aPtr,TUint aBit);
sl@0
    59
	void Flush();
sl@0
    60
private:
sl@0
    61
	TUint iBits;
sl@0
    62
	TUint8* iPtr;
sl@0
    63
	};
sl@0
    64
inline TWriteBitSequence::TWriteBitSequence()
sl@0
    65
	:iBits(0),iPtr(0) {}
sl@0
    66
TUint8* TWriteBitSequence::Write(TUint8* aPtr,TUint aBit)
sl@0
    67
	{
sl@0
    68
	TUint bits=iBits>>1;
sl@0
    69
	if ((bits&0x1000000)==0)
sl@0
    70
		{
sl@0
    71
		if (iPtr)
sl@0
    72
			*iPtr=TUint8(bits);
sl@0
    73
		iPtr=aPtr++;
sl@0
    74
		bits=0xff000000;
sl@0
    75
		}
sl@0
    76
	if (aBit)
sl@0
    77
		bits|=0x100;
sl@0
    78
	iBits=bits;
sl@0
    79
	return aPtr;
sl@0
    80
	}
sl@0
    81
void TWriteBitSequence::Flush()
sl@0
    82
	{
sl@0
    83
	TUint8* ptr=iPtr;
sl@0
    84
	if (ptr)
sl@0
    85
		{
sl@0
    86
		TUint bits=iBits;
sl@0
    87
		do bits>>=1; while (bits&0x1000000);
sl@0
    88
		*ptr=TUint8(bits);
sl@0
    89
		}
sl@0
    90
	}
sl@0
    91
#define WRITEBITINIT(This) TWriteBitSequence This
sl@0
    92
#define WRITEBIT(This,ptr,bit) ptr=This.Write(ptr,bit)
sl@0
    93
#define WRITEZEROBIT(This,ptr) ptr=This.Write(ptr,0)
sl@0
    94
#define FLUSHBITS(This) This.Flush()
sl@0
    95
#else
sl@0
    96
#define WRITEBITINIT(This) TUint32 This##_bits=0; TUint8* This##_ptr=0
sl@0
    97
#define NEXTBIT(This,ptr) This##_bits>>=1;if ((This##_bits&0x1000000)==0){if (This##_ptr) *This##_ptr=TUint8(This##_bits);This##_ptr=ptr++;This##_bits=0xff000000;}
sl@0
    98
#define WRITEZEROBIT(This,ptr) {NEXTBIT(This,ptr)}
sl@0
    99
#define WRITEBIT(This,ptr,bit) {NEXTBIT(This,ptr) if (bit) This##_bits|=0x100;}
sl@0
   100
#define FLUSHBITS(This) {if (This##_ptr){do This##_bits>>=1; while (This##_bits&0x1000000);*This##_ptr=TUint8(This##_bits);}}
sl@0
   101
#endif
sl@0
   102
sl@0
   103
LOCAL_C const TUint8* Read32(const TUint8* aPtr,TUint32* aDest)
sl@0
   104
// fast read for non-aligned little-endian 32-bit data
sl@0
   105
	{
sl@0
   106
	TUint32 x=*aPtr++;
sl@0
   107
	x|=*aPtr++<<8;
sl@0
   108
	x|=*aPtr++<<16;
sl@0
   109
	x|=*aPtr++<<24;
sl@0
   110
	*aDest=x;
sl@0
   111
	return aPtr;
sl@0
   112
	}
sl@0
   113
sl@0
   114
LOCAL_C TUint8* Write32(TUint8* aPtr,TUint32 aVal)
sl@0
   115
// fast transfer for non-aligned little-endian 32-bit data
sl@0
   116
	{
sl@0
   117
	*aPtr++=TUint8(aVal);
sl@0
   118
	*aPtr++=TUint8(aVal>>8);
sl@0
   119
	*aPtr++=TUint8(aVal>>16);
sl@0
   120
	*aPtr++=TUint8(aVal>>24);
sl@0
   121
	return aPtr;
sl@0
   122
	}
sl@0
   123
sl@0
   124
inline const TUint8* Read16(const TUint8* aPtr,TUint32* aDest)
sl@0
   125
// Read unsigned 16-bit value into aDest storage
sl@0
   126
	{
sl@0
   127
	TUint x=*aPtr++;
sl@0
   128
	x|=*aPtr++<<8;
sl@0
   129
	*aDest=TUint16(x);
sl@0
   130
	return aPtr;
sl@0
   131
	}
sl@0
   132
sl@0
   133
inline const TUint8* Read16s(const TUint8* aPtr,TUint32* aDest)
sl@0
   134
// Read signed 16-bit value into aDest storage
sl@0
   135
	{
sl@0
   136
	TInt x=*aPtr++<<16;
sl@0
   137
	x|=*aPtr++<<24;
sl@0
   138
	*aDest=x>>16;
sl@0
   139
	return aPtr;
sl@0
   140
	}
sl@0
   141
sl@0
   142
inline TUint8* Write16(TUint8* aPtr,TUint aVal)
sl@0
   143
// Write little-endian rep of the low 16 bits of aVal
sl@0
   144
	{
sl@0
   145
	*aPtr++=TUint8(aVal);
sl@0
   146
	*aPtr++=TUint8(aVal>>8);
sl@0
   147
	return aPtr;
sl@0
   148
	}
sl@0
   149
sl@0
   150
LOCAL_C TUint8* WriteCardinality(TUint8* aPtr,TUint aVal)
sl@0
   151
// compress cardinality into the data stream
sl@0
   152
	{
sl@0
   153
	__ASSERT(aVal<(1u<<30));
sl@0
   154
	if ((aVal>>7)==0)
sl@0
   155
		{
sl@0
   156
		*aPtr++=TUint8(aVal<<1);
sl@0
   157
		return aPtr;
sl@0
   158
		}
sl@0
   159
	aVal=(aVal<<2)|1;
sl@0
   160
	if ((aVal>>16)==0)
sl@0
   161
		{
sl@0
   162
		*aPtr++=TUint8(aVal);
sl@0
   163
		*aPtr++=TUint8(aVal>>8);
sl@0
   164
		return aPtr;
sl@0
   165
		}
sl@0
   166
	return Write32(aPtr,aVal|2);
sl@0
   167
	}
sl@0
   168
sl@0
   169
LOCAL_C TUint ReadCardinality(const TUint8* aPtr)
sl@0
   170
// extract cardinality from the data stream
sl@0
   171
	{
sl@0
   172
	TUint x=aPtr[0];
sl@0
   173
	if ((x&1)==0)
sl@0
   174
		return x>>1;
sl@0
   175
	x|=aPtr[1]<<8;
sl@0
   176
	if (x&2)
sl@0
   177
		{
sl@0
   178
		x|=aPtr[2]<<16;
sl@0
   179
		x|=aPtr[3]<<24;
sl@0
   180
		}
sl@0
   181
	return x>>2;
sl@0
   182
	}
sl@0
   183
sl@0
   184
LOCAL_C const TUint8* ReadCardinality(const TUint8* aPtr,TInt& aVal)
sl@0
   185
// extract cardinality from the data stream
sl@0
   186
	{
sl@0
   187
	TUint x=*aPtr++;
sl@0
   188
	if ((x&1)==0)
sl@0
   189
		x>>=1;
sl@0
   190
	else
sl@0
   191
		{
sl@0
   192
		x|=*aPtr++<<8;
sl@0
   193
		if (x&2)
sl@0
   194
			{
sl@0
   195
			x|=*aPtr++<<16;
sl@0
   196
			x|=*aPtr++<<24;
sl@0
   197
			}
sl@0
   198
		x>>=2;
sl@0
   199
		}
sl@0
   200
	aVal=x;
sl@0
   201
	return aPtr;
sl@0
   202
	}
sl@0
   203
sl@0
   204
LOCAL_C TInt SizeOfCardinality(TUint aVal)
sl@0
   205
// report the externalized size of the Compressed value in bytes
sl@0
   206
	{
sl@0
   207
	if ((aVal>>7)==0)
sl@0
   208
		return 1;
sl@0
   209
	return (aVal>>14)==0 ? 2 : 4;
sl@0
   210
	}
sl@0
   211
sl@0
   212
LOCAL_C TUint8* WriteBlobId(TUint8* aPtr,TDbBlobId aId)
sl@0
   213
	{
sl@0
   214
	return WriteCardinality(aPtr,(aId>>24)|(aId<<8>>4));
sl@0
   215
	}
sl@0
   216
sl@0
   217
LOCAL_C const TUint8* ReadBlobId(const TUint8* aPtr,TDbBlobId& aId)
sl@0
   218
	{
sl@0
   219
	aPtr=ReadCardinality(aPtr,*reinterpret_cast<TInt*>(&aId));
sl@0
   220
	aId=(aId>>4)|(aId<<28>>4);
sl@0
   221
	return aPtr;
sl@0
   222
	}
sl@0
   223
sl@0
   224
LOCAL_C TInt SizeOfBlobId(TDbBlobId aId)
sl@0
   225
	{
sl@0
   226
	return SizeOfCardinality((aId>>24)|(aId<<8>>4));
sl@0
   227
	}
sl@0
   228
sl@0
   229
// Class CDbStoreTable
sl@0
   230
sl@0
   231
CDbStoreTable::CDbStoreTable(CDbStoreDatabase& aDatabase,const CDbTableDef& aDef)
sl@0
   232
	: CDbTable(aDatabase,aDef)
sl@0
   233
	{}
sl@0
   234
sl@0
   235
CDbRecordSpace* CDbStoreTable::RecordSpaceL()
sl@0
   236
//
sl@0
   237
// open records handler
sl@0
   238
//
sl@0
   239
	{
sl@0
   240
	return CDbStoreRecords::NewL(Database().ClusterCacheL(),Def());
sl@0
   241
	}
sl@0
   242
sl@0
   243
CDbBlobSpace* CDbStoreTable::BlobSpaceL()
sl@0
   244
//
sl@0
   245
// Open a blobs accessor for the table
sl@0
   246
//
sl@0
   247
	{
sl@0
   248
	return new(ELeave) CDbStoreBlobs(Database(),Def().InlineLimit());
sl@0
   249
	}
sl@0
   250
sl@0
   251
CDbRecordIndex* CDbStoreTable::RecordIndexL(const CDbTableIndexDef& anIndex)
sl@0
   252
//
sl@0
   253
// Open an index
sl@0
   254
//
sl@0
   255
	{
sl@0
   256
	return CDbStoreIndex::NewL(Database(),(const CDbStoreIndexDef&)anIndex,Def());
sl@0
   257
	}
sl@0
   258
sl@0
   259
static TUint8* CompressUnicode(TUint8* aRec,const TAny* aData,TInt aSize)
sl@0
   260
//
sl@0
   261
// initially assume the compressed data requires 1 byte for the length data
sl@0
   262
// Copy it if more is necessary. This avoids having to run the compressor twice
sl@0
   263
//
sl@0
   264
	{
sl@0
   265
	TMemoryUnicodeSource source(reinterpret_cast<const TUint16*>(aData));
sl@0
   266
	TUnicodeCompressor compressor;
sl@0
   267
	TInt output;
sl@0
   268
	compressor.CompressL(aRec+1,source,KMaxTInt,aSize>>1,&output);
sl@0
   269
	TInt lenSize=SizeOfCardinality(output);
sl@0
   270
	if (lenSize!=1)
sl@0
   271
		Mem::Copy(aRec+lenSize,aRec+1,output);	// needs more space for length
sl@0
   272
	return WriteCardinality(aRec,output)+output;
sl@0
   273
	}
sl@0
   274
sl@0
   275
static TInt SizeOfCompressedUnicode(const TAny* aData,TInt aSize)
sl@0
   276
//
sl@0
   277
// bytes required to store the unicode data
sl@0
   278
//
sl@0
   279
	{
sl@0
   280
	TMemoryUnicodeSource source(reinterpret_cast<const TUint16*>(aData));
sl@0
   281
	TInt size=TUnicodeCompressor::CompressedSizeL(source,aSize>>1);
sl@0
   282
	return SizeOfCardinality(size)+size;
sl@0
   283
	}
sl@0
   284
sl@0
   285
static const TUint8* ExpandUnicodeL(const TUint8* aRec,TAny* aTarget,const TAny* aLimit,TInt& aChars)
sl@0
   286
//
sl@0
   287
// Read compressed unicode from the record
sl@0
   288
//
sl@0
   289
	{
sl@0
   290
	TInt bytes;
sl@0
   291
	aRec=ReadCardinality(aRec,bytes);
sl@0
   292
	TMemoryUnicodeSink unicode(reinterpret_cast<TUint16*>(aTarget));
sl@0
   293
	TUnicodeExpander expander;
sl@0
   294
	TInt used;
sl@0
   295
	expander.ExpandL(unicode,aRec,(TUint16*)aLimit-(TUint16*)aTarget,bytes,&aChars,&used);
sl@0
   296
	return bytes==used ? aRec+bytes : 0;	// signal corruption in data, could not fit text in space
sl@0
   297
	}
sl@0
   298
sl@0
   299
static TInt SizeOfExpandedUnicodeL(const TUint8* aData,TInt aSize)
sl@0
   300
//
sl@0
   301
// bytes required to store the unicode data
sl@0
   302
//
sl@0
   303
	{
sl@0
   304
	return TUnicodeExpander::ExpandedSizeL(aData,aSize)<<1;
sl@0
   305
	}
sl@0
   306
sl@0
   307
TInt CDbStoreTable::RecordLength(const RDbRow& aRow)
sl@0
   308
//
sl@0
   309
// Calculate the size of a record
sl@0
   310
//
sl@0
   311
	{
sl@0
   312
	TInt bits=SizeOfCardinality(OptimizedRowLength(aRow))<<3;		// record buffer size
sl@0
   313
	HDbColumnSet::TIteratorC col=Def().Columns().Begin();
sl@0
   314
	const TDbCell* const last=aRow.Last();
sl@0
   315
	for (const TDbCell* column=aRow.First();column<last;++col,column=column->Next())
sl@0
   316
		{
sl@0
   317
		__ASSERT(col<Def().Columns().End());	// columns off end
sl@0
   318
		TInt size=column->Length();
sl@0
   319
		if ((col->iAttributes&TDbCol::ENotNull)==0)
sl@0
   320
			{	//nullable
sl@0
   321
			++bits;
sl@0
   322
			if (size==0)
sl@0
   323
				continue;			// no data
sl@0
   324
			}
sl@0
   325
		__ASSERT(size>0);	// must be non-null to reach here
sl@0
   326
		TDbColType type=col->Type();
sl@0
   327
		__ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
sl@0
   328
		if (type==EDbColBit)
sl@0
   329
			++bits;
sl@0
   330
		else if (type<=EDbColDateTime)
sl@0
   331
			bits+=TRecordSize::FixedFieldSize(type)<<3;
sl@0
   332
		else if (type==EDbColText16)
sl@0
   333
			bits+=SizeOfCompressedUnicode(column->Data(),size)<<3;
sl@0
   334
		else if (type<=EDbColBinary)
sl@0
   335
			bits+=8+(size<<3);
sl@0
   336
		else
sl@0
   337
			{
sl@0
   338
			__ASSERT(type<=EDbColLongBinary);
sl@0
   339
			const TDbBlob& blob=*(const TDbBlob*)column->Data();
sl@0
   340
			if (!blob.IsInline())
sl@0
   341
				bits+=1+((SizeOfBlobId(blob.Id())+SizeOfCardinality(blob.Size()))<<3);
sl@0
   342
			else if (type!=EDbColLongText16)
sl@0
   343
				bits+=9+(blob.Size()<<3);
sl@0
   344
			else
sl@0
   345
				bits+=1+(SizeOfCompressedUnicode(blob.Data(),blob.Size())<<3);
sl@0
   346
			}
sl@0
   347
		}
sl@0
   348
	__ASSERT(bits<=(KDbStoreMaxRecordLength<<3));
sl@0
   349
	return (bits+7)>>3;
sl@0
   350
	}
sl@0
   351
sl@0
   352
TInt CDbStoreTable::OptimizedRowLength(const RDbRow& aRow)
sl@0
   353
//
sl@0
   354
// Calculate the minimal row buffer size (in words) to store the row data
sl@0
   355
//
sl@0
   356
	{
sl@0
   357
	HDbColumnSet::TIteratorC col=Def().Columns().Begin();
sl@0
   358
	const TDbCell* const last=aRow.Last();
sl@0
   359
	TInt cellHead=0;
sl@0
   360
	TInt words=0;
sl@0
   361
	for (const TDbCell* column=aRow.First();column<last;++col,column=column->Next())
sl@0
   362
		{
sl@0
   363
		++cellHead;
sl@0
   364
		__ASSERT(col<Def().Columns().End());	// columns off end
sl@0
   365
		TInt size=column->Length();
sl@0
   366
		if (size==0)
sl@0
   367
			continue;
sl@0
   368
		words+=cellHead;
sl@0
   369
		cellHead=0;
sl@0
   370
		TDbColType type=col->Type();
sl@0
   371
		__ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
sl@0
   372
		if (type<=EDbColDateTime)
sl@0
   373
			__ASSERT(size==(size>>2<<2));
sl@0
   374
		else if (type<=EDbColBinary)
sl@0
   375
			;
sl@0
   376
		else
sl@0
   377
			size=((const TDbBlob*)column->Data())->CellSize();
sl@0
   378
		words+=(size+3)>>2;
sl@0
   379
		}
sl@0
   380
	return words;
sl@0
   381
	}
sl@0
   382
sl@0
   383
void CDbStoreTable::CopyFromRow(TUint8* aRecord,const RDbRow& aRow)
sl@0
   384
//
sl@0
   385
// translate the row buffer into its persistent format in the record buffer
sl@0
   386
//
sl@0
   387
	{
sl@0
   388
	aRecord=WriteCardinality(aRecord,OptimizedRowLength(aRow));	// internal size
sl@0
   389
//
sl@0
   390
	WRITEBITINIT(bits);
sl@0
   391
	HDbColumnSet::TIteratorC iter=Def().Columns().Begin();
sl@0
   392
	const TDbCell* const last=aRow.Last();
sl@0
   393
	for (const TDbCell* column=aRow.First();column<last;++iter,column=column->Next())
sl@0
   394
		{
sl@0
   395
		__ASSERT(iter<Def().Columns().End());	// columns off end
sl@0
   396
		TInt size=column->Length();
sl@0
   397
		if ((iter->iAttributes&TDbCol::ENotNull)==0)
sl@0
   398
			{	// nullable
sl@0
   399
			WRITEBIT(bits,aRecord,size!=0);
sl@0
   400
			if (size==0)
sl@0
   401
				continue;			// no data
sl@0
   402
			}
sl@0
   403
		__ASSERT(size>0);	// must be non-null to reach here
sl@0
   404
		const TUint32* data=(const TUint32*)column->Data();
sl@0
   405
		TDbColType type=iter->Type();
sl@0
   406
		switch (type)
sl@0
   407
			{
sl@0
   408
		default:
sl@0
   409
			__ASSERT(0);
sl@0
   410
		case EDbColBit:
sl@0
   411
			WRITEBIT(bits,aRecord,*data);
sl@0
   412
			break;
sl@0
   413
		case EDbColInt8:
sl@0
   414
		case EDbColUint8:
sl@0
   415
			*aRecord++=TUint8(*data);
sl@0
   416
			break;
sl@0
   417
		case EDbColInt16:
sl@0
   418
		case EDbColUint16:
sl@0
   419
			aRecord=Write16(aRecord,*data);
sl@0
   420
			break;
sl@0
   421
#if defined(__DOUBLE_WORDS_SWAPPED__)
sl@0
   422
		case EDbColReal64:
sl@0
   423
			aRecord=Write32(aRecord,data[1]);	// write low word out first
sl@0
   424
			// drop through to write high word next
sl@0
   425
#endif
sl@0
   426
		case EDbColInt32:
sl@0
   427
		case EDbColUint32:
sl@0
   428
		case EDbColReal32:
sl@0
   429
			aRecord=Write32(aRecord,*data);
sl@0
   430
			break;
sl@0
   431
#if !defined(__DOUBLE_WORDS_SWAPPED__)
sl@0
   432
		case EDbColReal64:
sl@0
   433
#endif
sl@0
   434
		case EDbColInt64:
sl@0
   435
		case EDbColDateTime:
sl@0
   436
			aRecord=Write32(aRecord,data[0]);
sl@0
   437
			aRecord=Write32(aRecord,data[1]);
sl@0
   438
			break;
sl@0
   439
		case EDbColText16:
sl@0
   440
			aRecord=CompressUnicode(aRecord,data,size);
sl@0
   441
			break;
sl@0
   442
		case EDbColText8:
sl@0
   443
		case EDbColBinary:
sl@0
   444
			*aRecord++=TUint8(size);
sl@0
   445
			aRecord=Mem::Copy(aRecord,data,size);
sl@0
   446
			break;
sl@0
   447
		case EDbColLongText8:
sl@0
   448
		case EDbColLongText16:
sl@0
   449
		case EDbColLongBinary:
sl@0
   450
			{
sl@0
   451
			const TDbBlob& blob=*reinterpret_cast<const TDbBlob*>(data);
sl@0
   452
			size=blob.Size();
sl@0
   453
			WRITEBIT(bits,aRecord,blob.IsInline());
sl@0
   454
			if (blob.IsInline())
sl@0
   455
				{
sl@0
   456
				if (type==EDbColLongText16)
sl@0
   457
					aRecord=CompressUnicode(aRecord,blob.Data(),size);
sl@0
   458
				else
sl@0
   459
					{
sl@0
   460
					*aRecord++=TUint8(size);
sl@0
   461
					aRecord=Mem::Copy(aRecord,blob.Data(),size);
sl@0
   462
					}
sl@0
   463
				}
sl@0
   464
			else
sl@0
   465
				{
sl@0
   466
				aRecord=WriteBlobId(aRecord,blob.Id());
sl@0
   467
				aRecord=WriteCardinality(aRecord,size);
sl@0
   468
				}
sl@0
   469
			}
sl@0
   470
			break;
sl@0
   471
			}
sl@0
   472
		}
sl@0
   473
	FLUSHBITS(bits);
sl@0
   474
	}
sl@0
   475
sl@0
   476
const TUint8* CDbStoreTable::CopyToRowL(TDbCell* aCell,TInt aSize,const TUint8* aRec)
sl@0
   477
//
sl@0
   478
// translate persistent record into the row buffer
sl@0
   479
//
sl@0
   480
	{
sl@0
   481
	__ASSERT(aSize>0);
sl@0
   482
//
sl@0
   483
	const TDbCell* const end=PtrAdd(aCell,aSize);
sl@0
   484
	READBITINIT(bits);
sl@0
   485
	HDbColumnSet::TIteratorC col=Def().Columns().Begin();
sl@0
   486
	HDbColumnSet::TIteratorC const cend=Def().Columns().End();
sl@0
   487
	for (;;)
sl@0
   488
		{
sl@0
   489
		TInt size=0; //null data
sl@0
   490
		if (col->iAttributes&TDbCol::ENotNull || READBIT(bits,aRec))	// have data
sl@0
   491
			{
sl@0
   492
			if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TUint32))
sl@0
   493
				return 0;
sl@0
   494
			size=sizeof(TUint32);	// for most types
sl@0
   495
			TDbColType type=col->Type();
sl@0
   496
			switch (type)
sl@0
   497
				{
sl@0
   498
			default:
sl@0
   499
				__ASSERT(0);
sl@0
   500
			case EDbColBit:
sl@0
   501
				*(TUint32*)aCell->Data()=READBIT(bits,aRec);
sl@0
   502
				break;
sl@0
   503
			case EDbColInt8:
sl@0
   504
				*(TInt32*)aCell->Data()=*(const TInt8*)aRec;
sl@0
   505
				aRec+=sizeof(TInt8);
sl@0
   506
				break;
sl@0
   507
			case EDbColUint8:
sl@0
   508
				*(TUint32*)aCell->Data()=*aRec;
sl@0
   509
				aRec+=sizeof(TUint8);
sl@0
   510
				break;
sl@0
   511
			case EDbColInt16:
sl@0
   512
				aRec=Read16s(aRec,(TUint32*)aCell->Data());
sl@0
   513
				break;
sl@0
   514
			case EDbColUint16:
sl@0
   515
				aRec=Read16(aRec,(TUint32*)aCell->Data());
sl@0
   516
				break;
sl@0
   517
	#if defined(__DOUBLE_WORDS_SWAPPED__)
sl@0
   518
			case EDbColReal64:
sl@0
   519
				if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TReal64))
sl@0
   520
					return 0;
sl@0
   521
				size=sizeof(TReal64);
sl@0
   522
				aRec=Read32(aRec,(TUint32*)aCell->Data()+1);	// transfer low word first, to high address
sl@0
   523
				// drop through to transfer high word to low address!
sl@0
   524
	#endif
sl@0
   525
			case EDbColInt32:
sl@0
   526
			case EDbColUint32:
sl@0
   527
			case EDbColReal32:
sl@0
   528
				aRec=Read32(aRec,(TUint32*)aCell->Data());
sl@0
   529
				break;
sl@0
   530
	#if !defined(__DOUBLE_WORDS_SWAPPED__)
sl@0
   531
			case EDbColReal64:
sl@0
   532
	#endif
sl@0
   533
			case EDbColInt64:
sl@0
   534
			case EDbColDateTime:
sl@0
   535
				if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TInt64))
sl@0
   536
					return 0;
sl@0
   537
				size=sizeof(TInt64);
sl@0
   538
				aRec=Read32(aRec,(TUint32*)aCell->Data());
sl@0
   539
				aRec=Read32(aRec,(TUint32*)aCell->Data()+1);
sl@0
   540
				break;
sl@0
   541
			case EDbColText16:
sl@0
   542
				{
sl@0
   543
				TInt len;
sl@0
   544
				aRec=ExpandUnicodeL(aRec,aCell->Data(),end,len);
sl@0
   545
				if (!aRec)
sl@0
   546
					return 0;
sl@0
   547
				size=len<<1;
sl@0
   548
				}
sl@0
   549
				break;
sl@0
   550
			case EDbColText8:
sl@0
   551
			case EDbColBinary:
sl@0
   552
				size=*aRec++;
sl@0
   553
				if (TInt(end)-TInt(aCell)<TInt(size+sizeof(TUint32)))
sl@0
   554
					return 0;
sl@0
   555
				Mem::Copy(aCell->Data(),aRec,size);
sl@0
   556
				aRec+=size;
sl@0
   557
				break;
sl@0
   558
			case EDbColLongText8:
sl@0
   559
			case EDbColLongText16:
sl@0
   560
			case EDbColLongBinary:
sl@0
   561
				if (READBIT(bits,aRec)==0)
sl@0
   562
					{	// out of line Long column
sl@0
   563
					if (TInt(end)-TInt(aCell)<=TDbBlob::RefSize())
sl@0
   564
						return 0;
sl@0
   565
					TDbBlobId id;
sl@0
   566
					aRec=ReadBlobId(aRec,id);
sl@0
   567
					TInt sz;
sl@0
   568
					aRec=ReadCardinality(aRec,sz);
sl@0
   569
					new(aCell->Data()) TDbBlob(id,sz);
sl@0
   570
					size=TDbBlob::RefSize();
sl@0
   571
					}
sl@0
   572
				else if (type!=EDbColLongText16)
sl@0
   573
					{	// inline
sl@0
   574
					size=*aRec++;
sl@0
   575
					if (TInt(end)-TInt(aCell)<TInt(TDbBlob::InlineSize(size)+sizeof(TUint32)))
sl@0
   576
						return 0;
sl@0
   577
					new(aCell->Data()) TDbBlob(aRec,size);
sl@0
   578
					aRec+=size;
sl@0
   579
					size=TDbBlob::InlineSize(size);
sl@0
   580
					}
sl@0
   581
				else
sl@0
   582
					{
sl@0
   583
					TDbBlob* blob=new(aCell->Data()) TDbBlob;
sl@0
   584
					TInt len;
sl@0
   585
					aRec=ExpandUnicodeL(aRec,blob->InlineBuffer(),end,len);
sl@0
   586
					if (!aRec)
sl@0
   587
						return 0;
sl@0
   588
					size=len<<1;
sl@0
   589
					blob->SetSize(size);
sl@0
   590
					size=TDbBlob::InlineSize(size);
sl@0
   591
					}
sl@0
   592
				break;
sl@0
   593
				}
sl@0
   594
			}
sl@0
   595
		aCell->SetLength(size);
sl@0
   596
		aCell=aCell->Next();
sl@0
   597
		if (aCell==end)
sl@0
   598
			return aRec;
sl@0
   599
		if (++col==cend)
sl@0
   600
			return 0;
sl@0
   601
		}
sl@0
   602
	}
sl@0
   603
sl@0
   604
void CDbStoreTable::CopyToRowL(RDbRow& aRow,const TDesC8& aRecord)
sl@0
   605
//
sl@0
   606
// translate persistent record into the row buffer
sl@0
   607
//
sl@0
   608
	{
sl@0
   609
	const TUint8* rec=aRecord.Ptr();
sl@0
   610
	const TUint8* end=rec+aRecord.Length();
sl@0
   611
	TInt size;
sl@0
   612
	rec=ReadCardinality(rec,size);
sl@0
   613
	size<<=2;
sl@0
   614
	
sl@0
   615
	//If such huge allocation is requested(KMaxTInt/2), it is highly likely the file is corrupt
sl@0
   616
	if((size < 0) || (size >= KMaxTInt/2))
sl@0
   617
		{
sl@0
   618
		aRow.SetSize(0);
sl@0
   619
		__LEAVE(KErrCorrupt);
sl@0
   620
		}
sl@0
   621
	
sl@0
   622
	if (size)
sl@0
   623
		{
sl@0
   624
		aRow.GrowL(size);
sl@0
   625
		rec=CopyToRowL(aRow.First(),size,rec);
sl@0
   626
		}
sl@0
   627
	if (rec)
sl@0
   628
		{
sl@0
   629
		do
sl@0
   630
			{
sl@0
   631
			if (rec==end)
sl@0
   632
				{
sl@0
   633
	aRow.SetSize(size);
sl@0
   634
				return;
sl@0
   635
				}
sl@0
   636
			} while (*rec++==0);
sl@0
   637
		}
sl@0
   638
	aRow.SetSize(0);
sl@0
   639
	__LEAVE(KErrCorrupt);
sl@0
   640
	}
sl@0
   641
sl@0
   642
TUint8* CDbStoreTable::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength,TInt aInlineLimit)
sl@0
   643
//
sl@0
   644
// Rewrite the record in the buffer by removing the data from the delete-list
sl@0
   645
// any changes are recorded in the iAltered member
sl@0
   646
//
sl@0
   647
	{
sl@0
   648
	// initially assume that the length count will be the same size after alteration
sl@0
   649
	TInt lenSize=SizeOfCardinality(ReadCardinality(aRPtr));
sl@0
   650
	const TUint8* const rEnd=aRPtr+aLength;
sl@0
   651
	aRPtr+=lenSize;
sl@0
   652
	TUint8* wptr=aWPtr+lenSize;
sl@0
   653
	TInt wRowSize=0;
sl@0
   654
	TInt headers=0;
sl@0
   655
//
sl@0
   656
	READBITINIT(rbits);
sl@0
   657
	WRITEBITINIT(wbits);
sl@0
   658
	const HDbColumnSet::TIteratorC cEnd=Def().Columns().End();
sl@0
   659
	HDbColumnSet::TIteratorC col=Def().Columns().Begin();
sl@0
   660
	do
sl@0
   661
		{
sl@0
   662
		if (aRPtr==rEnd && !READHASBITS(rbits))
sl@0
   663
			break;	// no more data
sl@0
   664
		TUint flg=col->iFlags;
sl@0
   665
		if ((flg&TDbColumnDef::EDropped)==0)
sl@0
   666
			++headers;
sl@0
   667
		if ((col->iAttributes&TDbCol::ENotNull)==0)
sl@0
   668
			{	// nullable
sl@0
   669
			TUint notnull=READBIT(rbits,aRPtr);
sl@0
   670
			if ((flg&TDbColumnDef::EDropped)==0)
sl@0
   671
				WRITEBIT(wbits,wptr,notnull);
sl@0
   672
			if (notnull==0)	// null data
sl@0
   673
				continue;
sl@0
   674
			}
sl@0
   675
		wRowSize+=headers;
sl@0
   676
		headers=0;
sl@0
   677
		TInt size;
sl@0
   678
		TDbColType type=col->Type();
sl@0
   679
		switch (type)
sl@0
   680
			{
sl@0
   681
		default:
sl@0
   682
			__ASSERT(0);
sl@0
   683
		case EDbColBit:
sl@0
   684
			size=READBIT(rbits,aRPtr);
sl@0
   685
			if ((flg&TDbColumnDef::EDropped)==0)
sl@0
   686
				{
sl@0
   687
				WRITEBIT(wbits,wptr,size);
sl@0
   688
				++wRowSize;
sl@0
   689
				}
sl@0
   690
			continue;
sl@0
   691
		case EDbColInt8:
sl@0
   692
		case EDbColUint8:
sl@0
   693
		case EDbColInt16:
sl@0
   694
		case EDbColUint16:
sl@0
   695
		case EDbColInt32:
sl@0
   696
		case EDbColUint32:
sl@0
   697
		case EDbColReal32:
sl@0
   698
		case EDbColReal64:
sl@0
   699
		case EDbColInt64:
sl@0
   700
		case EDbColDateTime:
sl@0
   701
			size=TRecordSize::FixedFieldSize(type);
sl@0
   702
			if ((flg&TDbColumnDef::EDropped)==0)
sl@0
   703
				{
sl@0
   704
				wptr=Mem::Copy(wptr,aRPtr,size);
sl@0
   705
				wRowSize+=(size+3)>>2;	// # words
sl@0
   706
				}
sl@0
   707
			break;
sl@0
   708
		case EDbColText8:
sl@0
   709
		case EDbColBinary:
sl@0
   710
			size=*aRPtr++;
sl@0
   711
			if ((flg&(TDbColumnDef::EChangedType|TDbColumnDef::EDropped))==0)
sl@0
   712
				{
sl@0
   713
				wptr=Mem::Copy(wptr,aRPtr-1,size+1);	// no change, copy the column
sl@0
   714
				wRowSize+=(size+3)>>2;	// # words
sl@0
   715
				}
sl@0
   716
			else if (flg&TDbColumnDef::EChangedType)
sl@0
   717
				goto alterBlob8;	// type change, into a LongColumn
sl@0
   718
			else
sl@0
   719
				__ASSERT(flg&TDbColumnDef::EDropped);	// drop the column
sl@0
   720
			break;
sl@0
   721
		case EDbColText16:
sl@0
   722
			{
sl@0
   723
			TInt sz;
sl@0
   724
			aRPtr=ReadCardinality(aRPtr,sz);
sl@0
   725
			size=sz;
sl@0
   726
			if ((flg&(TDbColumnDef::EChangedType|TDbColumnDef::EDropped))==0)
sl@0
   727
				{
sl@0
   728
				wptr=WriteCardinality(wptr,size);
sl@0
   729
				wptr=Mem::Copy(wptr,aRPtr,size);	// no change, copy the column
sl@0
   730
				wRowSize+=(SizeOfExpandedUnicodeL(aRPtr,size)+3)>>2;
sl@0
   731
				}
sl@0
   732
			else if (flg&TDbColumnDef::EChangedType)
sl@0
   733
				goto alterBlob16;	// type change, into a LongColumn
sl@0
   734
			else
sl@0
   735
				__ASSERT(flg&TDbColumnDef::EDropped);	// drop the column
sl@0
   736
			}
sl@0
   737
			break;
sl@0
   738
		case EDbColLongText8:
sl@0
   739
		case EDbColLongBinary:
sl@0
   740
		case EDbColLongText16:
sl@0
   741
			if (!READBIT(rbits,aRPtr))
sl@0
   742
				{	// out-of-line
sl@0
   743
				TDbBlobId id;
sl@0
   744
				aRPtr=ReadBlobId(aRPtr,id);
sl@0
   745
				TInt sz;
sl@0
   746
				aRPtr=ReadCardinality(aRPtr,sz);
sl@0
   747
				if (flg&TDbColumnDef::EDropped)
sl@0
   748
					BlobsL()->DeleteL(id);	// delete the stream
sl@0
   749
				else
sl@0
   750
					{
sl@0
   751
					WRITEZEROBIT(wbits,wptr);			// out-of-line
sl@0
   752
					wptr=WriteBlobId(wptr,id);
sl@0
   753
					wptr=WriteCardinality(wptr,sz);
sl@0
   754
					wRowSize+=TDbBlob::RefSize()>>2;
sl@0
   755
					}
sl@0
   756
				size=0;
sl@0
   757
				}
sl@0
   758
			else if (type!=EDbColLongText16)
sl@0
   759
				{	// currently inline
sl@0
   760
				size=*aRPtr++;
sl@0
   761
				if (flg&TDbColumnDef::EDropped)
sl@0
   762
					break;
sl@0
   763
				// write long-column data, check inline status
sl@0
   764
alterBlob8:		WRITEBIT(wbits,wptr,size<=aInlineLimit);
sl@0
   765
				if (size<=aInlineLimit)
sl@0
   766
					{	// inlined
sl@0
   767
					*wptr++=TUint8(size);				// blob size
sl@0
   768
					wptr=Mem::Copy(wptr,aRPtr,size);	// blob data
sl@0
   769
					wRowSize+=(TDbBlob::InlineSize(size)+3)>>2;
sl@0
   770
					}
sl@0
   771
				else
sl@0
   772
					{
sl@0
   773
					TDbBlobId id=BlobsL()->CreateL(type,aRPtr,size);
sl@0
   774
					wptr=WriteBlobId(wptr,id);
sl@0
   775
					wptr=WriteCardinality(wptr,size);
sl@0
   776
					wRowSize+=TDbBlob::RefSize()>>2;
sl@0
   777
					}
sl@0
   778
				}
sl@0
   779
			else
sl@0
   780
				{	// currently inline
sl@0
   781
				TInt sz;
sl@0
   782
				aRPtr=ReadCardinality(aRPtr,sz);
sl@0
   783
				size=sz;
sl@0
   784
				if (flg&TDbColumnDef::EDropped)
sl@0
   785
					break;
sl@0
   786
				// write long-column data, check inline status
sl@0
   787
alterBlob16:	TInt len=SizeOfExpandedUnicodeL(aRPtr,size);
sl@0
   788
				WRITEBIT(wbits,wptr,len<=aInlineLimit);
sl@0
   789
				if (len<=aInlineLimit)
sl@0
   790
					{	// inlined
sl@0
   791
					wptr=WriteCardinality(wptr,size);
sl@0
   792
					wptr=Mem::Copy(wptr,aRPtr,size);	// blob data
sl@0
   793
					wRowSize+=(TDbBlob::InlineSize(len)+3)>>2;
sl@0
   794
					}
sl@0
   795
				else
sl@0
   796
					{
sl@0
   797
					TDbBlobId id=BlobsL()->CreateL(EDbColLongText8,aRPtr,size);	// no unicode compressor!
sl@0
   798
					wptr=WriteBlobId(wptr,id);
sl@0
   799
					wptr=WriteCardinality(wptr,len);
sl@0
   800
					wRowSize+=TDbBlob::RefSize()>>2;
sl@0
   801
					}
sl@0
   802
				}
sl@0
   803
			break;
sl@0
   804
			}
sl@0
   805
		aRPtr+=size;
sl@0
   806
		} while (++col<cEnd);
sl@0
   807
	FLUSHBITS(wbits);
sl@0
   808
	TInt lsz=SizeOfCardinality(wRowSize);
sl@0
   809
	if (lenSize!=lsz)
sl@0
   810
		wptr=Mem::Copy(aWPtr+lsz,aWPtr+lenSize,wptr-(aWPtr+lenSize));
sl@0
   811
	WriteCardinality(aWPtr,wRowSize);
sl@0
   812
	return wptr;
sl@0
   813
	}
sl@0
   814
sl@0
   815
TInt CDbStoreTable::IndexSpanL(const CDbTableIndexDef& aIndex,TUint aInclusion,const TDbLookupKey* aLower,const TDbLookupKey* aUpper)
sl@0
   816
//
sl@0
   817
// Guess the size of the index set contained in the given restriction
sl@0
   818
// First check the cached values in the defintion, and only load the index if necessary
sl@0
   819
//
sl@0
   820
	{
sl@0
   821
	const TDbStoreIndexStats& stats=static_cast<const CDbStoreIndexDef&>(aIndex).iStats;
sl@0
   822
	if (!stats.IsValid())
sl@0
   823
		IndexL(aIndex);				// ensure that the index is loaded
sl@0
   824
	return stats.Span(aInclusion,aLower,aUpper,TTextOps::Ops(aIndex.Key().Comparison()));
sl@0
   825
	}
sl@0
   826
sl@0
   827
// Class CDbStoreTable::CDiscarder
sl@0
   828
sl@0
   829
CDbStoreTable::CDiscarder::CDiscarder()
sl@0
   830
	{}
sl@0
   831
sl@0
   832
CDbStoreTable::CDiscarder::~CDiscarder()
sl@0
   833
	{
sl@0
   834
	if (iTable)
sl@0
   835
		iTable->Close();
sl@0
   836
	iRow.Close();
sl@0
   837
	}
sl@0
   838
sl@0
   839
TInt CDbStoreTable::CDiscarder::OpenL(CDbStoreTable* aTable)
sl@0
   840
	{
sl@0
   841
	__ASSERT(!iTable);
sl@0
   842
	iTable=aTable;
sl@0
   843
	iRecords=&aTable->StoreRecordsL();
sl@0
   844
	iCluster=iRecords->Head();
sl@0
   845
	return iRecords->Count()+1;
sl@0
   846
	}
sl@0
   847
sl@0
   848
TInt CDbStoreTable::CDiscarder::StepL(TInt aStep)
sl@0
   849
	{
sl@0
   850
	__ASSERT(iTable);
sl@0
   851
	TInt limit=iTable->Def().Columns().HasLongColumns() ? EBlobDiscardClusters : EDiscardClusters;
sl@0
   852
	for (TInt inc=0;inc<limit;++inc)
sl@0
   853
		{
sl@0
   854
		if (iCluster==KNullClusterId)
sl@0
   855
			{
sl@0
   856
			iRecords->DestroyL();
sl@0
   857
			return 0;
sl@0
   858
			}
sl@0
   859
		if (limit==EBlobDiscardClusters)
sl@0
   860
			iRecords->AlterL(iCluster,*this);
sl@0
   861
		aStep-=iRecords->DiscardL(iCluster);
sl@0
   862
		}
sl@0
   863
	return Max(aStep,1);
sl@0
   864
	}
sl@0
   865
sl@0
   866
TUint8* CDbStoreTable::CDiscarder::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength)
sl@0
   867
//
sl@0
   868
// Scan for and discard all known BLOBs
sl@0
   869
//
sl@0
   870
	{
sl@0
   871
	iTable->CopyToRowL(iRow,TPtrC8(aRPtr,aLength));
sl@0
   872
	iTable->DiscardBlobsL(iRow);
sl@0
   873
	return aWPtr;
sl@0
   874
	}
sl@0
   875
sl@0
   876
// class CDbStoreTable::CAlter
sl@0
   877
sl@0
   878
CDbStoreTable::CAlter::CAlter()
sl@0
   879
	{}
sl@0
   880
sl@0
   881
CDbStoreTable::CAlter::~CAlter()
sl@0
   882
	{
sl@0
   883
	if (iTable)
sl@0
   884
		iTable->Close();
sl@0
   885
	}
sl@0
   886
sl@0
   887
void CDbStoreTable::CAlter::OpenL(CDbStoreTable* aTable,const HDbColumnSet& aNewSet)
sl@0
   888
//
sl@0
   889
// Prepare for alteration of the table data
sl@0
   890
//
sl@0
   891
	{
sl@0
   892
	__ASSERT(!iTable);
sl@0
   893
	iTable=aTable;
sl@0
   894
	iInlineLimit=TRecordSize::InlineLimit(aNewSet);
sl@0
   895
	iRecords=&iTable->StoreRecordsL();
sl@0
   896
	iCluster=iRecords->Head();
sl@0
   897
//
sl@0
   898
// Calculate the maximum possible expansion, based on the changes to the column set
sl@0
   899
// Currently the only alloed change which affects this is Text->LongText type changes
sl@0
   900
// these all add a single bit
sl@0
   901
//
sl@0
   902
	TInt expand=0;
sl@0
   903
	const HDbColumnSet& columns=iTable->Def().Columns();
sl@0
   904
	const HDbColumnSet::TIteratorC end=columns.End();
sl@0
   905
	HDbColumnSet::TIteratorC col=columns.Begin();
sl@0
   906
	do
sl@0
   907
		{
sl@0
   908
		if (col->iFlags&TDbColumnDef::EChangedType)
sl@0
   909
			{
sl@0
   910
			__ASSERT(col->iType>=EDbColText8&&col->iType<=EDbColBinary);
sl@0
   911
			++expand;
sl@0
   912
			}
sl@0
   913
		} while (++col<end);
sl@0
   914
	iExpansion=(expand+7)>>3;
sl@0
   915
	}
sl@0
   916
sl@0
   917
TInt CDbStoreTable::CAlter::StepL(TInt aStep)
sl@0
   918
//
sl@0
   919
// Do some steps to alter the table data
sl@0
   920
//
sl@0
   921
	{
sl@0
   922
	__ASSERT(iTable);
sl@0
   923
	iStep=aStep;
sl@0
   924
	iCluster=iRecords->AlterL(iCluster,*this);
sl@0
   925
	return iCluster==KNullClusterId ? 0 : Max(iStep,1);
sl@0
   926
	}
sl@0
   927
sl@0
   928
TUint8* CDbStoreTable::CAlter::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength)
sl@0
   929
//
sl@0
   930
// providing for CClusterCache::MAlter
sl@0
   931
// re-write the record
sl@0
   932
//
sl@0
   933
	{
sl@0
   934
	--iStep;
sl@0
   935
	return iTable->AlterRecordL(aWPtr,aRPtr,aLength,iInlineLimit);
sl@0
   936
	}
sl@0
   937
sl@0
   938
TInt CDbStoreTable::CAlter::RecordExpansion(const TUint8*,TInt)
sl@0
   939
//
sl@0
   940
// providing for CClusterCache::MAlter
sl@0
   941
// just return the maximum possible expansion, rather than a record-specific one
sl@0
   942
//
sl@0
   943
	{
sl@0
   944
	return iExpansion;
sl@0
   945
	}