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.
17 #include "U32STD_DBMS.H"
18 #include <d32dbmsconstants.h>
22 TUint8 const TRecordSize::FieldSizes[]=
25 sizeof(TInt8), // EDbColInt8
26 sizeof(TUint8), // EDbColUint8
27 sizeof(TInt16), // EDbColInt16
28 sizeof(TUint16), // EDbColUint16
29 sizeof(TInt32), // EDbColInt32
30 sizeof(TUint32), // EDbColUint32
31 sizeof(TInt64), // EDbColInt64
32 sizeof(TReal32), // EDbColReal32
33 sizeof(TReal64), // EDbColReal64
34 sizeof(TTime) // EDbColDateTime
37 TBool TRecordSize::Set(const HDbColumnSet& aColumns)
39 // Calculate stats for the record size and shape from the definition
42 TInt fix=0,null=0,var=0,blob=0;
43 HDbColumnSet::TIteratorC const end=aColumns.End();
44 HDbColumnSet::TIteratorC col=aColumns.Begin();
47 TBool notnull=col->iAttributes&TDbCol::ENotNull;
50 TDbColType type=col->Type();
51 __ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
54 else if (type<=EDbColDateTime)
56 TInt bits=FixedFieldSize(type)<<3;
62 else if (type<=EDbColBinary)
64 TInt size=col->iMaxLength;
65 if (type==EDbColText16)
73 // assuming Blobs take at least 16 bytes + 1 bit
74 TInt max=(fix+null+var+blob*(1+(KMinInlineLimit<<3))+7)>>3;
75 if (max>KDbStoreMaxRecordLength)
78 // Assuming a Maximally full record, how much excess space is available for Blobs?
80 iInlineLimit=KDbMaxInlineBlobSize;
82 { // use the spare space for extra inlining
83 TInt spare=(KDbStoreMaxRecordLength-max);
84 TInt inl=spare/blob+KMinInlineLimit-1;
85 if (inl<KDbMaxInlineBlobSize)
89 // Calculate the average cluster size for a column set
90 // This assumes that the nullable columns are present 50%, Variable average 1/16
91 // Blobs achieve 16 bytes, or inline limit (if smaller)
93 TInt average=(fix+(null>>1)+(var>>4)+blob*(1+(16<<3))+7)>>3;
94 TInt clustering=KClusterLimit/average;
97 else if (clustering>KMaxClustering)
98 clustering=KMaxClustering;
99 iClustering=clustering;
103 void TRecordSize::CheckSizeL(const HDbColumnSet& aColumns)
105 // Check that the columns definition is a valid size
109 if (size.Set(aColumns))
113 TInt TRecordSize::InlineLimit(const HDbColumnSet& aColumns)
115 // Evaluate the inline limit for the column set. It is assumed to be valid
119 __DEBUG(TBool chk =)size.Set(aColumns);
121 return size.InlineLimit();
124 // Streaming column definitions
126 LOCAL_C void ExternalizeL(const TDbColumnDef& aCol,RWriteStream& aStream)
128 aStream<<*aCol.iName;
129 aStream.WriteUint8L(aCol.iType);
130 aStream.WriteUint8L(aCol.iAttributes);
136 aStream.WriteUint8L(aCol.iMaxLength);
143 LOCAL_C void InternalizeL(TDbColumnDef& aCol,RReadStream& aStream)
145 aCol.iName=HBufC::NewL(aStream,KDbMaxColName);
146 TDbColType type=TDbColType(aStream.ReadUint8L());
147 aCol.iType=TUint8(type);
148 aCol.iAttributes=aStream.ReadUint8L();
149 if (type>EDbColLongBinary || (aCol.iAttributes&~(TDbCol::ENotNull|TDbCol::EAutoIncrement))!=0)
150 __LEAVE(KErrCorrupt);
151 if (type>=EDbColText8 && type<=EDbColBinary)
153 aCol.iMaxLength=aStream.ReadUint8L();
154 if (aCol.iMaxLength==0)
155 __LEAVE(KErrCorrupt);
158 aCol.iMaxLength=KDbUndefinedLength;
161 inline RWriteStream& operator<<(RWriteStream& aStream,const TDbColumnDef& aCol)
162 {ExternalizeL(aCol,aStream);return aStream;}
163 inline RReadStream& operator>>(RReadStream& aStream,TDbColumnDef& aCol)
164 {InternalizeL(aCol,aStream);return aStream;}
166 // Streaming key columns
168 LOCAL_C void ExternalizeL(const TDbKeyCol& aKeyCol,RWriteStream& aStream)
170 aStream<<aKeyCol.iName;
171 aStream.WriteUint8L(aKeyCol.iLength!=KDbUndefinedLength ? aKeyCol.iLength : 0);
172 aStream.WriteUint8L(aKeyCol.iOrder);
175 LOCAL_C void InternalizeL(TDbKeyCol& aKeyCol,RReadStream& aStream)
177 TPtr des=aKeyCol.iName.Des();
179 TUint len=aStream.ReadUint8L();
180 aKeyCol.iLength=len!=0 ? TInt(len) : KDbUndefinedLength;
181 aKeyCol.iOrder=TDbKeyCol::TOrder(aStream.ReadUint8L());
182 if (aKeyCol.iOrder>TDbKeyCol::EDesc)
183 __LEAVE(KErrCorrupt);
186 inline RWriteStream& operator<<(RWriteStream& aStream,const TDbKeyCol& aCol)
187 {ExternalizeL(aCol,aStream);return aStream;}
188 inline RReadStream& operator>>(RReadStream& aStream,TDbKeyCol& aCol)
189 {InternalizeL(aCol,aStream);return aStream;}
192 // Class CDbStoreIndexDef
194 CDbStoreIndexDef::CDbStoreIndexDef()
197 CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName)
199 CDbStoreIndexDef* self=new(ELeave) CDbStoreIndexDef;
200 CleanupStack::PushL(self);
201 self->ConstructL(aName);
205 CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName,const CDbKey& aKey,const HDbColumnSet& aColumns)
207 CDbStoreIndexDef* self=NewLC(aName);
208 CDbKey& key=self->Key();
209 TInt max=aKey.Count();
210 for (TInt ii=0;ii<max;++ii)
212 TDbKeyCol kCol=aKey[ii];
213 const TDbColumnDef& col=*aColumns.ColumnL(kCol.iName);
220 if (kCol.iLength==KDbUndefinedLength)
221 kCol.iLength=col.iMaxLength;
223 case EDbColLongText8:
224 case EDbColLongText16:
225 if (kCol.iLength==KDbUndefinedLength)
226 __LEAVE(KErrArgument);
229 case EDbColLongBinary:
230 __LEAVE(KErrArgument);
237 if (aKey.IsPrimary())
239 key.SetComparison(aKey.Comparison());
240 CheckSizeL(key,aColumns);
244 CDbStoreIndexDef* CDbStoreIndexDef::NewL(RReadStream& aStream)
246 // Construct an index definition from persistent storage
251 CDbStoreIndexDef* self=NewLC(name);
252 CDbKey& key=self->Key();
253 TDbTextComparison comp=TDbTextComparison(aStream.ReadUint8L());
254 if (comp>EDbCompareCollated)
255 __LEAVE(KErrCorrupt);
256 key.SetComparison(comp);
257 if (aStream.ReadUint8L())
261 for (TInt ii=count;ii>0;--ii)
267 aStream>>self->iTokenId;
272 void CDbStoreIndexDef::ExternalizeL(RWriteStream& aStream) const
275 const CDbKey& key=Key();
276 aStream.WriteUint8L(TUint8(key.Comparison()));
277 aStream.WriteUint8L(key.IsUnique());
278 TInt max=key.Count();
279 aStream<<TCardinality(max);
280 for (TInt ii=0;ii<max;++ii)
285 TInt CDbStoreIndexDef::KeySize(const TDbKeyCol& aKeyCol,const TDbColumnDef& aColumn)
287 LOCAL_D const TUint8 KFixedSize[]=
301 TDbColType t=aColumn.Type();
302 if (TUint(t)<sizeof(KFixedSize)/sizeof(KFixedSize[0]))
303 return KFixedSize[t];
309 case EDbColLongText8:
310 return aKeyCol.iLength;
312 case EDbColLongText16:
313 return aKeyCol.iLength<<1;
317 void CDbStoreIndexDef::CheckSizeL(const CDbKey& aKey,const HDbColumnSet& aColSet)
319 // Check the size of the key for the index definition
322 TInt len=aKey.IsUnique()?0:sizeof(TDbRecordId);
323 for (TInt ii=aKey.Count();--ii>=0;)
325 const TDbKeyCol& keyCol=aKey[ii];
326 len+=Align4(KeySize(keyCol,*aColSet.ColumnL(keyCol.iName)));
328 if (len>KMaxIndexKeySize)
335 LOCAL_C void SetColumnL(TDbColumnDef& aDef,const TDbCol& aCol,TUint aFlag=0)
338 if (aDef.iAttributes&TDbCol::EAutoIncrement)
339 aDef.iAttributes|=TDbCol::ENotNull; // auto-increment => not-null
340 aDef.iFlags=TUint8(aFlag);
341 TDbColType type=aCol.iType;
342 if (type>=EDbColText8 && type<=EDbColBinary)
344 if (aCol.iMaxLength==KDbUndefinedLength)
345 aDef.iMaxLength=KDbStoreMaxColumnLength;
346 else if (aCol.iMaxLength>KDbStoreMaxColumnLength)
347 __LEAVE(KErrNotSupported);
350 aDef.iMaxLength=KDbUndefinedLength;
353 LOCAL_C HDbColumnSet::TIterator CheckColumnsL(HDbColumnSet::TIterator anIter,const CDbColSet& aColSet,TInt aNotNull,TUint aFlag=0)
355 // Check the columns from aColset into anIter, according to ENotNull attribute
359 for (TDbColSetIter iter(aColSet);iter;++iter)
361 TInt att=iter->iAttributes;
362 if (att&TDbCol::EAutoIncrement)
363 att|=TDbCol::ENotNull; // auto-increment => not-null
364 if ((att&TDbCol::ENotNull)==aNotNull)
366 SetColumnL(*anIter,*iter,aFlag);
373 CDbStoreDef::CDbStoreDef()
376 CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,TInt aColumnCount)
378 CDbStoreDef* self=new(ELeave) CDbStoreDef;
379 CleanupStack::PushL(self);
380 self->ConstructL(aName,aColumnCount);
384 CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,const CDbColSet& aColSet)
386 // Construct a table definition from the column set supplied
389 CDbStoreDef* self=NewLC(aName,aColSet.Count());
390 HDbColumnSet& columns=self->Columns();
391 HDbColumnSet::TIterator def=CheckColumnsL(columns.Begin(),aColSet,TDbCol::ENotNull);
392 def=CheckColumnsL(def,aColSet,0);
393 __ASSERT(def==columns.End());
394 TRecordSize::CheckSizeL(columns);
399 CDbStoreDef* CDbStoreDef::NewL(RReadStream& aStream)
401 // Construct a table definition from persistent storage
408 CDbStoreDef* self=NewLC(name,count);
409 HDbColumnSet& columns=self->Columns();
410 HDbColumnSet::TIterator iter=columns.Begin();
411 const HDbColumnSet::TIteratorC end=columns.End();
415 } while (++iter<end);
418 if (cluster==0 || cluster>KMaxClustering)
419 __LEAVE(KErrCorrupt);
420 aStream>>self->iTokenId;
421 RDbIndexes& indexes=self->Indexes();
423 for (TInt ii=count;ii>0;--ii)
424 indexes.Add(CDbStoreIndexDef::NewL(aStream));
430 void CDbStoreDef::Changed()
432 // The definition has changed, following creation or alteration of the table
433 // Recalculate cached data for the definition.
436 CDbTableDef::Changed();
437 __DEBUG(TBool dbg =)iInfo.Set(Columns());
441 void CDbStoreDef::ExternalizeL(RWriteStream& aStream) const
444 const HDbColumnSet& columns=Columns();
445 aStream<<TCardinality(columns.Count());
446 HDbColumnSet::TIteratorC iter=columns.Begin();
447 const HDbColumnSet::TIteratorC end=columns.End();
451 } while (++iter<end);
452 aStream<<TCardinality(Clustering()); // old stuff, not needed
454 aStream<<TCardinality(Indexes().Count());
455 TSglQueIterC<CDbStoreIndexDef> ixIter(Indexes().AsQue());
456 for (const CDbStoreIndexDef* def;(def=ixIter++)!=0;)
460 void CDbStoreDef::AlteredColumnSetL(HDbColumnSet& aSet,const CDbColSet& aChange,const CDbColSet& aAdd)
462 // Generate an altered column set
463 // We can hijack the non-user attribs of the column sets for marking changes
466 // add not-null columns to the front
467 HDbColumnSet::TIterator newCol=CheckColumnsL(aSet.Begin(),aAdd,TDbCol::ENotNull,TDbColumnDef::EAdded);
468 // copy current set, minus deleted ones, apply text column length changes
469 TDbColSetIter change(aChange);
470 HDbColumnSet::TIterator col=Columns().Begin();
471 HDbColumnSet::TIteratorC const end=Columns().End();
474 TUint flag=col->iFlags;
475 if (flag&TDbColumnDef::EDropped)
477 if (flag&(TDbColumnDef::EChangedType|TDbColumnDef::EChangedLen))
479 // check allowed changes
480 SetColumnL(*newCol,*change);
482 if (flag&TDbColumnDef::EChangedType)
483 { // validate type changes (only text->longtext etc)
484 if (!TDbCol::IsLong(newCol->Type()) || newCol->iType-col->iType!=3)
485 __LEAVE(KErrNotSupported);
489 col->iFlags=TUint8(flag&~TDbColumnDef::EChangedLen); // no real changes req'd
490 if (newCol->iMaxLength<col->iMaxLength)
491 __LEAVE(KErrNotSupported); // can only extend columns
498 // add nullable columns to the end
499 newCol=CheckColumnsL(newCol,aAdd,0,TDbColumnDef::EAdded);
500 __ASSERT(newCol==aSet.End());
501 TRecordSize::CheckSizeL(aSet);