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