Update contrib.
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.
18 //#define __READBIT_CLASS
19 //#define __WRITEBIT_CLASS
21 #ifdef __READBIT_CLASS
22 class TReadBitSequence
25 inline TReadBitSequence();
26 inline TBool HasBits() const;
27 TUint Read(const TUint8*& aPtr);
31 inline TReadBitSequence::TReadBitSequence()
33 inline TBool TReadBitSequence::HasBits() const
34 {return (iBits&0x2000000);}
35 TUint TReadBitSequence::Read(const TUint8*& aPtr)
38 if ((iBits&0x1000000)==0)
39 iBits=*aPtr++ | 0xff000000u;
42 #define READBITINIT(This) TReadBitSequence This
43 #define READHASBITS(This) This.HasBits()
44 #define READBIT(This,ptr) This.Read(ptr)
45 #define SKIPBIT(This,ptr) READBIT(This,ptr)
47 #define READBITINIT(This) TUint This##_bits=0
48 #define READHASBITS(This) (This##_bits&0x2000000)
49 #define SKIPBIT(This,ptr) (This##_bits>>=1,(This##_bits&0x1000000 ? void(0) : void(This##_bits=*ptr++|0xff000000u)))
50 #define READBIT(This,ptr) (SKIPBIT(This,ptr),This##_bits&1)
53 #ifdef __WRITEBIT_CLASS
54 class TWriteBitSequence
57 inline TWriteBitSequence();
58 TUint8* Write(TUint8* aPtr,TUint aBit);
64 inline TWriteBitSequence::TWriteBitSequence()
66 TUint8* TWriteBitSequence::Write(TUint8* aPtr,TUint aBit)
69 if ((bits&0x1000000)==0)
81 void TWriteBitSequence::Flush()
87 do bits>>=1; while (bits&0x1000000);
91 #define WRITEBITINIT(This) TWriteBitSequence This
92 #define WRITEBIT(This,ptr,bit) ptr=This.Write(ptr,bit)
93 #define WRITEZEROBIT(This,ptr) ptr=This.Write(ptr,0)
94 #define FLUSHBITS(This) This.Flush()
96 #define WRITEBITINIT(This) TUint32 This##_bits=0; TUint8* This##_ptr=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;}
98 #define WRITEZEROBIT(This,ptr) {NEXTBIT(This,ptr)}
99 #define WRITEBIT(This,ptr,bit) {NEXTBIT(This,ptr) if (bit) This##_bits|=0x100;}
100 #define FLUSHBITS(This) {if (This##_ptr){do This##_bits>>=1; while (This##_bits&0x1000000);*This##_ptr=TUint8(This##_bits);}}
103 LOCAL_C const TUint8* Read32(const TUint8* aPtr,TUint32* aDest)
104 // fast read for non-aligned little-endian 32-bit data
114 LOCAL_C TUint8* Write32(TUint8* aPtr,TUint32 aVal)
115 // fast transfer for non-aligned little-endian 32-bit data
117 *aPtr++=TUint8(aVal);
118 *aPtr++=TUint8(aVal>>8);
119 *aPtr++=TUint8(aVal>>16);
120 *aPtr++=TUint8(aVal>>24);
124 inline const TUint8* Read16(const TUint8* aPtr,TUint32* aDest)
125 // Read unsigned 16-bit value into aDest storage
133 inline const TUint8* Read16s(const TUint8* aPtr,TUint32* aDest)
134 // Read signed 16-bit value into aDest storage
142 inline TUint8* Write16(TUint8* aPtr,TUint aVal)
143 // Write little-endian rep of the low 16 bits of aVal
145 *aPtr++=TUint8(aVal);
146 *aPtr++=TUint8(aVal>>8);
150 LOCAL_C TUint8* WriteCardinality(TUint8* aPtr,TUint aVal)
151 // compress cardinality into the data stream
153 __ASSERT(aVal<(1u<<30));
156 *aPtr++=TUint8(aVal<<1);
162 *aPtr++=TUint8(aVal);
163 *aPtr++=TUint8(aVal>>8);
166 return Write32(aPtr,aVal|2);
169 LOCAL_C TUint ReadCardinality(const TUint8* aPtr)
170 // extract cardinality from the data stream
184 LOCAL_C const TUint8* ReadCardinality(const TUint8* aPtr,TInt& aVal)
185 // extract cardinality from the data stream
204 LOCAL_C TInt SizeOfCardinality(TUint aVal)
205 // report the externalized size of the Compressed value in bytes
209 return (aVal>>14)==0 ? 2 : 4;
212 LOCAL_C TUint8* WriteBlobId(TUint8* aPtr,TDbBlobId aId)
214 return WriteCardinality(aPtr,(aId>>24)|(aId<<8>>4));
217 LOCAL_C const TUint8* ReadBlobId(const TUint8* aPtr,TDbBlobId& aId)
219 aPtr=ReadCardinality(aPtr,*reinterpret_cast<TInt*>(&aId));
220 aId=(aId>>4)|(aId<<28>>4);
224 LOCAL_C TInt SizeOfBlobId(TDbBlobId aId)
226 return SizeOfCardinality((aId>>24)|(aId<<8>>4));
229 // Class CDbStoreTable
231 CDbStoreTable::CDbStoreTable(CDbStoreDatabase& aDatabase,const CDbTableDef& aDef)
232 : CDbTable(aDatabase,aDef)
235 CDbRecordSpace* CDbStoreTable::RecordSpaceL()
237 // open records handler
240 return CDbStoreRecords::NewL(Database().ClusterCacheL(),Def());
243 CDbBlobSpace* CDbStoreTable::BlobSpaceL()
245 // Open a blobs accessor for the table
248 return new(ELeave) CDbStoreBlobs(Database(),Def().InlineLimit());
251 CDbRecordIndex* CDbStoreTable::RecordIndexL(const CDbTableIndexDef& anIndex)
256 return CDbStoreIndex::NewL(Database(),(const CDbStoreIndexDef&)anIndex,Def());
259 static TUint8* CompressUnicode(TUint8* aRec,const TAny* aData,TInt aSize)
261 // initially assume the compressed data requires 1 byte for the length data
262 // Copy it if more is necessary. This avoids having to run the compressor twice
265 TMemoryUnicodeSource source(reinterpret_cast<const TUint16*>(aData));
266 TUnicodeCompressor compressor;
268 compressor.CompressL(aRec+1,source,KMaxTInt,aSize>>1,&output);
269 TInt lenSize=SizeOfCardinality(output);
271 Mem::Copy(aRec+lenSize,aRec+1,output); // needs more space for length
272 return WriteCardinality(aRec,output)+output;
275 static TInt SizeOfCompressedUnicode(const TAny* aData,TInt aSize)
277 // bytes required to store the unicode data
280 TMemoryUnicodeSource source(reinterpret_cast<const TUint16*>(aData));
281 TInt size=TUnicodeCompressor::CompressedSizeL(source,aSize>>1);
282 return SizeOfCardinality(size)+size;
285 static const TUint8* ExpandUnicode(const TUint8* aRec,TAny* aTarget,const TAny* aLimit,TInt& aChars)
287 // Read compressed unicode from the record
291 aRec=ReadCardinality(aRec,bytes);
292 TMemoryUnicodeSink unicode(reinterpret_cast<TUint16*>(aTarget));
293 TUnicodeExpander expander;
295 expander.ExpandL(unicode,aRec,(TUint16*)aLimit-(TUint16*)aTarget,bytes,&aChars,&used);
296 return bytes==used ? aRec+bytes : 0; // signal corruption in data, could not fit text in space
299 static TInt SizeOfExpandedUnicode(const TUint8* aData,TInt aSize)
301 // bytes required to store the unicode data
304 return TUnicodeExpander::ExpandedSizeL(aData,aSize)<<1;
307 TInt CDbStoreTable::RecordLength(const RDbRow& aRow)
309 // Calculate the size of a record
312 TInt bits=SizeOfCardinality(OptimizedRowLength(aRow))<<3; // record buffer size
313 HDbColumnSet::TIteratorC col=Def().Columns().Begin();
314 const TDbCell* const last=aRow.Last();
315 for (const TDbCell* column=aRow.First();column<last;++col,column=column->Next())
317 __ASSERT(col<Def().Columns().End()); // columns off end
318 TInt size=column->Length();
319 if ((col->iAttributes&TDbCol::ENotNull)==0)
325 __ASSERT(size>0); // must be non-null to reach here
326 TDbColType type=col->Type();
327 __ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
330 else if (type<=EDbColDateTime)
331 bits+=TRecordSize::FixedFieldSize(type)<<3;
332 else if (type==EDbColText16)
333 bits+=SizeOfCompressedUnicode(column->Data(),size)<<3;
334 else if (type<=EDbColBinary)
338 __ASSERT(type<=EDbColLongBinary);
339 const TDbBlob& blob=*(const TDbBlob*)column->Data();
340 if (!blob.IsInline())
341 bits+=1+((SizeOfBlobId(blob.Id())+SizeOfCardinality(blob.Size()))<<3);
342 else if (type!=EDbColLongText16)
343 bits+=9+(blob.Size()<<3);
345 bits+=1+(SizeOfCompressedUnicode(blob.Data(),blob.Size())<<3);
348 __ASSERT(bits<=(KDbStoreMaxRecordLength<<3));
352 TInt CDbStoreTable::OptimizedRowLength(const RDbRow& aRow)
354 // Calculate the minimal row buffer size (in words) to store the row data
357 HDbColumnSet::TIteratorC col=Def().Columns().Begin();
358 const TDbCell* const last=aRow.Last();
361 for (const TDbCell* column=aRow.First();column<last;++col,column=column->Next())
364 __ASSERT(col<Def().Columns().End()); // columns off end
365 TInt size=column->Length();
370 TDbColType type=col->Type();
371 __ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
372 if (type<=EDbColDateTime)
373 __ASSERT(size==(size>>2<<2));
374 else if (type<=EDbColBinary)
377 size=((const TDbBlob*)column->Data())->CellSize();
383 void CDbStoreTable::CopyFromRow(TUint8* aRecord,const RDbRow& aRow)
385 // translate the row buffer into its persistent format in the record buffer
388 aRecord=WriteCardinality(aRecord,OptimizedRowLength(aRow)); // internal size
391 HDbColumnSet::TIteratorC iter=Def().Columns().Begin();
392 const TDbCell* const last=aRow.Last();
393 for (const TDbCell* column=aRow.First();column<last;++iter,column=column->Next())
395 __ASSERT(iter<Def().Columns().End()); // columns off end
396 TInt size=column->Length();
397 if ((iter->iAttributes&TDbCol::ENotNull)==0)
399 WRITEBIT(bits,aRecord,size!=0);
403 __ASSERT(size>0); // must be non-null to reach here
404 const TUint32* data=(const TUint32*)column->Data();
405 TDbColType type=iter->Type();
411 WRITEBIT(bits,aRecord,*data);
415 *aRecord++=TUint8(*data);
419 aRecord=Write16(aRecord,*data);
421 #if defined(__DOUBLE_WORDS_SWAPPED__)
423 aRecord=Write32(aRecord,data[1]); // write low word out first
424 // drop through to write high word next
429 aRecord=Write32(aRecord,*data);
431 #if !defined(__DOUBLE_WORDS_SWAPPED__)
436 aRecord=Write32(aRecord,data[0]);
437 aRecord=Write32(aRecord,data[1]);
440 aRecord=CompressUnicode(aRecord,data,size);
444 *aRecord++=TUint8(size);
445 aRecord=Mem::Copy(aRecord,data,size);
447 case EDbColLongText8:
448 case EDbColLongText16:
449 case EDbColLongBinary:
451 const TDbBlob& blob=*reinterpret_cast<const TDbBlob*>(data);
453 WRITEBIT(bits,aRecord,blob.IsInline());
456 if (type==EDbColLongText16)
457 aRecord=CompressUnicode(aRecord,blob.Data(),size);
460 *aRecord++=TUint8(size);
461 aRecord=Mem::Copy(aRecord,blob.Data(),size);
466 aRecord=WriteBlobId(aRecord,blob.Id());
467 aRecord=WriteCardinality(aRecord,size);
476 const TUint8* CDbStoreTable::CopyToRow(TDbCell* aCell,TInt aSize,const TUint8* aRec)
478 // translate persistent record into the row buffer
483 const TDbCell* const end=PtrAdd(aCell,aSize);
485 HDbColumnSet::TIteratorC col=Def().Columns().Begin();
486 HDbColumnSet::TIteratorC const cend=Def().Columns().End();
489 TInt size=0; //null data
490 if (col->iAttributes&TDbCol::ENotNull || READBIT(bits,aRec)) // have data
492 if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TUint32))
494 size=sizeof(TUint32); // for most types
495 TDbColType type=col->Type();
501 *(TUint32*)aCell->Data()=READBIT(bits,aRec);
504 *(TInt32*)aCell->Data()=*(const TInt8*)aRec;
508 *(TUint32*)aCell->Data()=*aRec;
509 aRec+=sizeof(TUint8);
512 aRec=Read16s(aRec,(TUint32*)aCell->Data());
515 aRec=Read16(aRec,(TUint32*)aCell->Data());
517 #if defined(__DOUBLE_WORDS_SWAPPED__)
519 if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TReal64))
521 size=sizeof(TReal64);
522 aRec=Read32(aRec,(TUint32*)aCell->Data()+1); // transfer low word first, to high address
523 // drop through to transfer high word to low address!
528 aRec=Read32(aRec,(TUint32*)aCell->Data());
530 #if !defined(__DOUBLE_WORDS_SWAPPED__)
535 if (TInt(end)-TInt(aCell)<=(TInt)sizeof(TInt64))
538 aRec=Read32(aRec,(TUint32*)aCell->Data());
539 aRec=Read32(aRec,(TUint32*)aCell->Data()+1);
544 aRec=ExpandUnicode(aRec,aCell->Data(),end,len);
553 if (TInt(end)-TInt(aCell)<TInt(size+sizeof(TUint32)))
555 Mem::Copy(aCell->Data(),aRec,size);
558 case EDbColLongText8:
559 case EDbColLongText16:
560 case EDbColLongBinary:
561 if (READBIT(bits,aRec)==0)
562 { // out of line Long column
563 if (TInt(end)-TInt(aCell)<=TDbBlob::RefSize())
566 aRec=ReadBlobId(aRec,id);
568 aRec=ReadCardinality(aRec,sz);
569 new(aCell->Data()) TDbBlob(id,sz);
570 size=TDbBlob::RefSize();
572 else if (type!=EDbColLongText16)
575 if (TInt(end)-TInt(aCell)<TInt(TDbBlob::InlineSize(size)+sizeof(TUint32)))
577 new(aCell->Data()) TDbBlob(aRec,size);
579 size=TDbBlob::InlineSize(size);
583 TDbBlob* blob=new(aCell->Data()) TDbBlob;
585 aRec=ExpandUnicode(aRec,blob->InlineBuffer(),end,len);
590 size=TDbBlob::InlineSize(size);
595 aCell->SetLength(size);
604 void CDbStoreTable::CopyToRowL(RDbRow& aRow,const TDesC8& aRecord)
606 // translate persistent record into the row buffer
609 const TUint8* rec=aRecord.Ptr();
610 const TUint8* end=rec+aRecord.Length();
612 rec=ReadCardinality(rec,size);
617 __LEAVE(KErrCorrupt);
623 rec=CopyToRow(aRow.First(),size,rec);
637 __LEAVE(KErrCorrupt);
640 TUint8* CDbStoreTable::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength,TInt aInlineLimit)
642 // Rewrite the record in the buffer by removing the data from the delete-list
643 // any changes are recorded in the iAltered member
646 // initially assume that the length count will be the same size after alteration
647 TInt lenSize=SizeOfCardinality(ReadCardinality(aRPtr));
648 const TUint8* const rEnd=aRPtr+aLength;
650 TUint8* wptr=aWPtr+lenSize;
656 const HDbColumnSet::TIteratorC cEnd=Def().Columns().End();
657 HDbColumnSet::TIteratorC col=Def().Columns().Begin();
660 if (aRPtr==rEnd && !READHASBITS(rbits))
661 break; // no more data
662 TUint flg=col->iFlags;
663 if ((flg&TDbColumnDef::EDropped)==0)
665 if ((col->iAttributes&TDbCol::ENotNull)==0)
667 TUint notnull=READBIT(rbits,aRPtr);
668 if ((flg&TDbColumnDef::EDropped)==0)
669 WRITEBIT(wbits,wptr,notnull);
670 if (notnull==0) // null data
676 TDbColType type=col->Type();
682 size=READBIT(rbits,aRPtr);
683 if ((flg&TDbColumnDef::EDropped)==0)
685 WRITEBIT(wbits,wptr,size);
699 size=TRecordSize::FixedFieldSize(type);
700 if ((flg&TDbColumnDef::EDropped)==0)
702 wptr=Mem::Copy(wptr,aRPtr,size);
703 wRowSize+=(size+3)>>2; // # words
709 if ((flg&(TDbColumnDef::EChangedType|TDbColumnDef::EDropped))==0)
711 wptr=Mem::Copy(wptr,aRPtr-1,size+1); // no change, copy the column
712 wRowSize+=(size+3)>>2; // # words
714 else if (flg&TDbColumnDef::EChangedType)
715 goto alterBlob8; // type change, into a LongColumn
717 __ASSERT(flg&TDbColumnDef::EDropped); // drop the column
722 aRPtr=ReadCardinality(aRPtr,sz);
724 if ((flg&(TDbColumnDef::EChangedType|TDbColumnDef::EDropped))==0)
726 wptr=WriteCardinality(wptr,size);
727 wptr=Mem::Copy(wptr,aRPtr,size); // no change, copy the column
728 wRowSize+=(SizeOfExpandedUnicode(aRPtr,size)+3)>>2;
730 else if (flg&TDbColumnDef::EChangedType)
731 goto alterBlob16; // type change, into a LongColumn
733 __ASSERT(flg&TDbColumnDef::EDropped); // drop the column
736 case EDbColLongText8:
737 case EDbColLongBinary:
738 case EDbColLongText16:
739 if (!READBIT(rbits,aRPtr))
742 aRPtr=ReadBlobId(aRPtr,id);
744 aRPtr=ReadCardinality(aRPtr,sz);
745 if (flg&TDbColumnDef::EDropped)
746 BlobsL()->DeleteL(id); // delete the stream
749 WRITEZEROBIT(wbits,wptr); // out-of-line
750 wptr=WriteBlobId(wptr,id);
751 wptr=WriteCardinality(wptr,sz);
752 wRowSize+=TDbBlob::RefSize()>>2;
756 else if (type!=EDbColLongText16)
757 { // currently inline
759 if (flg&TDbColumnDef::EDropped)
761 // write long-column data, check inline status
762 alterBlob8: WRITEBIT(wbits,wptr,size<=aInlineLimit);
763 if (size<=aInlineLimit)
765 *wptr++=TUint8(size); // blob size
766 wptr=Mem::Copy(wptr,aRPtr,size); // blob data
767 wRowSize+=(TDbBlob::InlineSize(size)+3)>>2;
771 TDbBlobId id=BlobsL()->CreateL(type,aRPtr,size);
772 wptr=WriteBlobId(wptr,id);
773 wptr=WriteCardinality(wptr,size);
774 wRowSize+=TDbBlob::RefSize()>>2;
778 { // currently inline
780 aRPtr=ReadCardinality(aRPtr,sz);
782 if (flg&TDbColumnDef::EDropped)
784 // write long-column data, check inline status
785 alterBlob16: TInt len=SizeOfExpandedUnicode(aRPtr,size);
786 WRITEBIT(wbits,wptr,len<=aInlineLimit);
787 if (len<=aInlineLimit)
789 wptr=WriteCardinality(wptr,size);
790 wptr=Mem::Copy(wptr,aRPtr,size); // blob data
791 wRowSize+=(TDbBlob::InlineSize(len)+3)>>2;
795 TDbBlobId id=BlobsL()->CreateL(EDbColLongText8,aRPtr,size); // no unicode compressor!
796 wptr=WriteBlobId(wptr,id);
797 wptr=WriteCardinality(wptr,len);
798 wRowSize+=TDbBlob::RefSize()>>2;
804 } while (++col<cEnd);
806 TInt lsz=SizeOfCardinality(wRowSize);
808 wptr=Mem::Copy(aWPtr+lsz,aWPtr+lenSize,wptr-(aWPtr+lenSize));
809 WriteCardinality(aWPtr,wRowSize);
813 TInt CDbStoreTable::IndexSpanL(const CDbTableIndexDef& aIndex,TUint aInclusion,const TDbLookupKey* aLower,const TDbLookupKey* aUpper)
815 // Guess the size of the index set contained in the given restriction
816 // First check the cached values in the defintion, and only load the index if necessary
819 const TDbStoreIndexStats& stats=static_cast<const CDbStoreIndexDef&>(aIndex).iStats;
820 if (!stats.IsValid())
821 IndexL(aIndex); // ensure that the index is loaded
822 return stats.Span(aInclusion,aLower,aUpper,TTextOps::Ops(aIndex.Key().Comparison()));
825 // Class CDbStoreTable::CDiscarder
827 CDbStoreTable::CDiscarder::CDiscarder()
830 CDbStoreTable::CDiscarder::~CDiscarder()
837 TInt CDbStoreTable::CDiscarder::OpenL(CDbStoreTable* aTable)
841 iRecords=&aTable->StoreRecordsL();
842 iCluster=iRecords->Head();
843 return iRecords->Count()+1;
846 TInt CDbStoreTable::CDiscarder::StepL(TInt aStep)
849 TInt limit=iTable->Def().Columns().HasLongColumns() ? EBlobDiscardClusters : EDiscardClusters;
850 for (TInt inc=0;inc<limit;++inc)
852 if (iCluster==KNullClusterId)
854 iRecords->DestroyL();
857 if (limit==EBlobDiscardClusters)
858 iRecords->AlterL(iCluster,*this);
859 aStep-=iRecords->DiscardL(iCluster);
864 TUint8* CDbStoreTable::CDiscarder::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength)
866 // Scan for and discard all known BLOBs
869 iTable->CopyToRowL(iRow,TPtrC8(aRPtr,aLength));
870 iTable->DiscardBlobsL(iRow);
874 // class CDbStoreTable::CAlter
876 CDbStoreTable::CAlter::CAlter()
879 CDbStoreTable::CAlter::~CAlter()
885 void CDbStoreTable::CAlter::OpenL(CDbStoreTable* aTable,const HDbColumnSet& aNewSet)
887 // Prepare for alteration of the table data
892 iInlineLimit=TRecordSize::InlineLimit(aNewSet);
893 iRecords=&iTable->StoreRecordsL();
894 iCluster=iRecords->Head();
896 // Calculate the maximum possible expansion, based on the changes to the column set
897 // Currently the only alloed change which affects this is Text->LongText type changes
898 // these all add a single bit
901 const HDbColumnSet& columns=iTable->Def().Columns();
902 const HDbColumnSet::TIteratorC end=columns.End();
903 HDbColumnSet::TIteratorC col=columns.Begin();
906 if (col->iFlags&TDbColumnDef::EChangedType)
908 __ASSERT(col->iType>=EDbColText8&&col->iType<=EDbColBinary);
912 iExpansion=(expand+7)>>3;
915 TInt CDbStoreTable::CAlter::StepL(TInt aStep)
917 // Do some steps to alter the table data
922 iCluster=iRecords->AlterL(iCluster,*this);
923 return iCluster==KNullClusterId ? 0 : Max(iStep,1);
926 TUint8* CDbStoreTable::CAlter::AlterRecordL(TUint8* aWPtr,const TUint8* aRPtr,TInt aLength)
928 // providing for CClusterCache::MAlter
929 // re-write the record
933 return iTable->AlterRecordL(aWPtr,aRPtr,aLength,iInlineLimit);
936 TInt CDbStoreTable::CAlter::RecordExpansion(const TUint8*,TInt)
938 // providing for CClusterCache::MAlter
939 // just return the maximum possible expansion, rather than a record-specific one