1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/dbms/pcdbms/ustor/US_SCHMA.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,503 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "US_STD.H"
1.20 +#include "U32STD_DBMS.H"
1.21 +#include <d32dbmsconstants.h>
1.22 +
1.23 +// class TRecordSize
1.24 +
1.25 +TUint8 const TRecordSize::FieldSizes[]=
1.26 + {
1.27 + 0, // EDbColBit
1.28 + sizeof(TInt8), // EDbColInt8
1.29 + sizeof(TUint8), // EDbColUint8
1.30 + sizeof(TInt16), // EDbColInt16
1.31 + sizeof(TUint16), // EDbColUint16
1.32 + sizeof(TInt32), // EDbColInt32
1.33 + sizeof(TUint32), // EDbColUint32
1.34 + sizeof(TInt64), // EDbColInt64
1.35 + sizeof(TReal32), // EDbColReal32
1.36 + sizeof(TReal64), // EDbColReal64
1.37 + sizeof(TTime) // EDbColDateTime
1.38 + };
1.39 +
1.40 +TBool TRecordSize::Set(const HDbColumnSet& aColumns)
1.41 +//
1.42 +// Calculate stats for the record size and shape from the definition
1.43 +//
1.44 + {
1.45 + TInt fix=0,null=0,var=0,blob=0;
1.46 + HDbColumnSet::TIteratorC const end=aColumns.End();
1.47 + HDbColumnSet::TIteratorC col=aColumns.Begin();
1.48 + do
1.49 + {
1.50 + TBool notnull=col->iAttributes&TDbCol::ENotNull;
1.51 + if (notnull==0)
1.52 + ++fix;
1.53 + TDbColType type=col->Type();
1.54 + __ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
1.55 + if (type==EDbColBit)
1.56 + ++fix;
1.57 + else if (type<=EDbColDateTime)
1.58 + {
1.59 + TInt bits=FixedFieldSize(type)<<3;
1.60 + if (notnull)
1.61 + fix+=bits;
1.62 + else
1.63 + null+=bits;
1.64 + }
1.65 + else if (type<=EDbColBinary)
1.66 + {
1.67 + TInt size=col->iMaxLength;
1.68 + if (type==EDbColText16)
1.69 + size<<=1;
1.70 + var+=8+(size<<3);
1.71 + }
1.72 + else
1.73 + ++blob;
1.74 + } while(++col<end);
1.75 +//
1.76 +// assuming Blobs take at least 16 bytes + 1 bit
1.77 + TInt max=(fix+null+var+blob*(1+(KMinInlineLimit<<3))+7)>>3;
1.78 + if (max>KDbStoreMaxRecordLength)
1.79 + return ETrue;
1.80 +//
1.81 +// Assuming a Maximally full record, how much excess space is available for Blobs?
1.82 +//
1.83 + iInlineLimit=KDbMaxInlineBlobSize;
1.84 + if (blob)
1.85 + { // use the spare space for extra inlining
1.86 + TInt spare=(KDbStoreMaxRecordLength-max);
1.87 + TInt inl=spare/blob+KMinInlineLimit-1;
1.88 + if (inl<KDbMaxInlineBlobSize)
1.89 + iInlineLimit=inl;
1.90 + }
1.91 +//
1.92 +// Calculate the average cluster size for a column set
1.93 +// This assumes that the nullable columns are present 50%, Variable average 1/16
1.94 +// Blobs achieve 16 bytes, or inline limit (if smaller)
1.95 +//
1.96 + TInt average=(fix+(null>>1)+(var>>4)+blob*(1+(16<<3))+7)>>3;
1.97 + TInt clustering=KClusterLimit/average;
1.98 + if (clustering==0)
1.99 + clustering=1;
1.100 + else if (clustering>KMaxClustering)
1.101 + clustering=KMaxClustering;
1.102 + iClustering=clustering;
1.103 + return EFalse;
1.104 + }
1.105 +
1.106 +void TRecordSize::CheckSizeL(const HDbColumnSet& aColumns)
1.107 +//
1.108 +// Check that the columns definition is a valid size
1.109 +//
1.110 + {
1.111 + TRecordSize size;
1.112 + if (size.Set(aColumns))
1.113 + __LEAVE(KErrTooBig);
1.114 + }
1.115 +
1.116 +TInt TRecordSize::InlineLimit(const HDbColumnSet& aColumns)
1.117 +//
1.118 +// Evaluate the inline limit for the column set. It is assumed to be valid
1.119 +//
1.120 + {
1.121 + TRecordSize size;
1.122 + __DEBUG(TBool chk =)size.Set(aColumns);
1.123 + __ASSERT(!chk);
1.124 + return size.InlineLimit();
1.125 + }
1.126 +
1.127 +// Streaming column definitions
1.128 +
1.129 +LOCAL_C void ExternalizeL(const TDbColumnDef& aCol,RWriteStream& aStream)
1.130 + {
1.131 + aStream<<*aCol.iName;
1.132 + aStream.WriteUint8L(aCol.iType);
1.133 + aStream.WriteUint8L(aCol.iAttributes);
1.134 + switch (aCol.iType)
1.135 + {
1.136 + case EDbColBinary:
1.137 + case EDbColText8:
1.138 + case EDbColText16:
1.139 + aStream.WriteUint8L(aCol.iMaxLength);
1.140 + break;
1.141 + default:
1.142 + break;
1.143 + }
1.144 + }
1.145 +
1.146 +LOCAL_C void InternalizeL(TDbColumnDef& aCol,RReadStream& aStream)
1.147 + {
1.148 + aCol.iName=HBufC::NewL(aStream,KDbMaxColName);
1.149 + TDbColType type=TDbColType(aStream.ReadUint8L());
1.150 + aCol.iType=TUint8(type);
1.151 + aCol.iAttributes=aStream.ReadUint8L();
1.152 + if (type>EDbColLongBinary || (aCol.iAttributes&~(TDbCol::ENotNull|TDbCol::EAutoIncrement))!=0)
1.153 + __LEAVE(KErrCorrupt);
1.154 + if (type>=EDbColText8 && type<=EDbColBinary)
1.155 + {
1.156 + aCol.iMaxLength=aStream.ReadUint8L();
1.157 + if (aCol.iMaxLength==0)
1.158 + __LEAVE(KErrCorrupt);
1.159 + }
1.160 + else
1.161 + aCol.iMaxLength=KDbUndefinedLength;
1.162 + }
1.163 +
1.164 +inline RWriteStream& operator<<(RWriteStream& aStream,const TDbColumnDef& aCol)
1.165 + {ExternalizeL(aCol,aStream);return aStream;}
1.166 +inline RReadStream& operator>>(RReadStream& aStream,TDbColumnDef& aCol)
1.167 + {InternalizeL(aCol,aStream);return aStream;}
1.168 +
1.169 +// Streaming key columns
1.170 +
1.171 +LOCAL_C void ExternalizeL(const TDbKeyCol& aKeyCol,RWriteStream& aStream)
1.172 + {
1.173 + aStream<<aKeyCol.iName;
1.174 + aStream.WriteUint8L(aKeyCol.iLength!=KDbUndefinedLength ? aKeyCol.iLength : 0);
1.175 + aStream.WriteUint8L(aKeyCol.iOrder);
1.176 + }
1.177 +
1.178 +LOCAL_C void InternalizeL(TDbKeyCol& aKeyCol,RReadStream& aStream)
1.179 + {
1.180 + TPtr des=aKeyCol.iName.Des();
1.181 + aStream>>des;
1.182 + TUint len=aStream.ReadUint8L();
1.183 + aKeyCol.iLength=len!=0 ? TInt(len) : KDbUndefinedLength;
1.184 + aKeyCol.iOrder=TDbKeyCol::TOrder(aStream.ReadUint8L());
1.185 + if (aKeyCol.iOrder>TDbKeyCol::EDesc)
1.186 + __LEAVE(KErrCorrupt);
1.187 + }
1.188 +
1.189 +inline RWriteStream& operator<<(RWriteStream& aStream,const TDbKeyCol& aCol)
1.190 + {ExternalizeL(aCol,aStream);return aStream;}
1.191 +inline RReadStream& operator>>(RReadStream& aStream,TDbKeyCol& aCol)
1.192 + {InternalizeL(aCol,aStream);return aStream;}
1.193 +
1.194 +
1.195 +// Class CDbStoreIndexDef
1.196 +
1.197 +CDbStoreIndexDef::CDbStoreIndexDef()
1.198 + {}
1.199 +
1.200 +CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName)
1.201 + {
1.202 + CDbStoreIndexDef* self=new(ELeave) CDbStoreIndexDef;
1.203 + CleanupStack::PushL(self);
1.204 + self->ConstructL(aName);
1.205 + return self;
1.206 + }
1.207 +
1.208 +CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName,const CDbKey& aKey,const HDbColumnSet& aColumns)
1.209 + {
1.210 + CDbStoreIndexDef* self=NewLC(aName);
1.211 + CDbKey& key=self->Key();
1.212 + TInt max=aKey.Count();
1.213 + for (TInt ii=0;ii<max;++ii)
1.214 + {
1.215 + TDbKeyCol kCol=aKey[ii];
1.216 + const TDbColumnDef& col=*aColumns.ColumnL(kCol.iName);
1.217 + switch (col.iType)
1.218 + {
1.219 + default:
1.220 + break;
1.221 + case EDbColText8:
1.222 + case EDbColText16:
1.223 + if (kCol.iLength==KDbUndefinedLength)
1.224 + kCol.iLength=col.iMaxLength;
1.225 + break;
1.226 + case EDbColLongText8:
1.227 + case EDbColLongText16:
1.228 + if (kCol.iLength==KDbUndefinedLength)
1.229 + __LEAVE(KErrArgument);
1.230 + break;
1.231 + case EDbColBinary:
1.232 + case EDbColLongBinary:
1.233 + __LEAVE(KErrArgument);
1.234 + break;
1.235 + }
1.236 + key.AddL(kCol);
1.237 + }
1.238 + if (aKey.IsUnique())
1.239 + key.MakeUnique();
1.240 + if (aKey.IsPrimary())
1.241 + key.MakePrimary();
1.242 + key.SetComparison(aKey.Comparison());
1.243 + CheckSizeL(key,aColumns);
1.244 + return self;
1.245 + }
1.246 +
1.247 +CDbStoreIndexDef* CDbStoreIndexDef::NewL(RReadStream& aStream)
1.248 +//
1.249 +// Construct an index definition from persistent storage
1.250 +//
1.251 + {
1.252 + TDbName name;
1.253 + aStream>>name;
1.254 + CDbStoreIndexDef* self=NewLC(name);
1.255 + CDbKey& key=self->Key();
1.256 + TDbTextComparison comp=TDbTextComparison(aStream.ReadUint8L());
1.257 + if (comp>EDbCompareCollated)
1.258 + __LEAVE(KErrCorrupt);
1.259 + key.SetComparison(comp);
1.260 + if (aStream.ReadUint8L())
1.261 + key.MakeUnique();
1.262 + TCardinality count;
1.263 + aStream>>count;
1.264 + for (TInt ii=count;ii>0;--ii)
1.265 + {
1.266 + TDbKeyCol keycol;
1.267 + aStream>>keycol;
1.268 + key.AddL(keycol);
1.269 + }
1.270 + aStream>>self->iTokenId;
1.271 + CleanupStack::Pop();
1.272 + return self;
1.273 + }
1.274 +
1.275 +void CDbStoreIndexDef::ExternalizeL(RWriteStream& aStream) const
1.276 + {
1.277 + aStream<<Name();
1.278 + const CDbKey& key=Key();
1.279 + aStream.WriteUint8L(TUint8(key.Comparison()));
1.280 + aStream.WriteUint8L(key.IsUnique());
1.281 + TInt max=key.Count();
1.282 + aStream<<TCardinality(max);
1.283 + for (TInt ii=0;ii<max;++ii)
1.284 + aStream<<key[ii];
1.285 + aStream<<iTokenId;
1.286 + }
1.287 +
1.288 +TInt CDbStoreIndexDef::KeySize(const TDbKeyCol& aKeyCol,const TDbColumnDef& aColumn)
1.289 + {
1.290 + LOCAL_D const TUint8 KFixedSize[]=
1.291 + {
1.292 + sizeof(TUint32),
1.293 + sizeof(TInt32),
1.294 + sizeof(TUint32),
1.295 + sizeof(TInt32),
1.296 + sizeof(TUint32),
1.297 + sizeof(TInt32),
1.298 + sizeof(TUint32),
1.299 + sizeof(TInt64),
1.300 + sizeof(TReal32),
1.301 + sizeof(TReal64),
1.302 + sizeof(TTime)
1.303 + };
1.304 + TDbColType t=aColumn.Type();
1.305 + if (TUint(t)<sizeof(KFixedSize)/sizeof(KFixedSize[0]))
1.306 + return KFixedSize[t];
1.307 + switch (t)
1.308 + {
1.309 + default:
1.310 + __ASSERT(0);
1.311 + case EDbColText8:
1.312 + case EDbColLongText8:
1.313 + return aKeyCol.iLength;
1.314 + case EDbColText16:
1.315 + case EDbColLongText16:
1.316 + return aKeyCol.iLength<<1;
1.317 + }
1.318 + }
1.319 +
1.320 +void CDbStoreIndexDef::CheckSizeL(const CDbKey& aKey,const HDbColumnSet& aColSet)
1.321 +//
1.322 +// Check the size of the key for the index definition
1.323 +//
1.324 + {
1.325 + TInt len=aKey.IsUnique()?0:sizeof(TDbRecordId);
1.326 + for (TInt ii=aKey.Count();--ii>=0;)
1.327 + {
1.328 + const TDbKeyCol& keyCol=aKey[ii];
1.329 + len+=Align4(KeySize(keyCol,*aColSet.ColumnL(keyCol.iName)));
1.330 + }
1.331 + if (len>KMaxIndexKeySize)
1.332 + __LEAVE(KErrTooBig);
1.333 + }
1.334 +
1.335 +
1.336 +// Class CDbStoreDef
1.337 +
1.338 +LOCAL_C void SetColumnL(TDbColumnDef& aDef,const TDbCol& aCol,TUint aFlag=0)
1.339 + {
1.340 + aDef.SetL(aCol);
1.341 + if (aDef.iAttributes&TDbCol::EAutoIncrement)
1.342 + aDef.iAttributes|=TDbCol::ENotNull; // auto-increment => not-null
1.343 + aDef.iFlags=TUint8(aFlag);
1.344 + TDbColType type=aCol.iType;
1.345 + if (type>=EDbColText8 && type<=EDbColBinary)
1.346 + {
1.347 + if (aCol.iMaxLength==KDbUndefinedLength)
1.348 + aDef.iMaxLength=KDbStoreMaxColumnLength;
1.349 + else if (aCol.iMaxLength>KDbStoreMaxColumnLength)
1.350 + __LEAVE(KErrNotSupported);
1.351 + }
1.352 + else
1.353 + aDef.iMaxLength=KDbUndefinedLength;
1.354 + }
1.355 +
1.356 +LOCAL_C HDbColumnSet::TIterator CheckColumnsL(HDbColumnSet::TIterator anIter,const CDbColSet& aColSet,TInt aNotNull,TUint aFlag=0)
1.357 +//
1.358 +// Check the columns from aColset into anIter, according to ENotNull attribute
1.359 +// Validate as we go
1.360 +//
1.361 + {
1.362 + for (TDbColSetIter iter(aColSet);iter;++iter)
1.363 + {
1.364 + TInt att=iter->iAttributes;
1.365 + if (att&TDbCol::EAutoIncrement)
1.366 + att|=TDbCol::ENotNull; // auto-increment => not-null
1.367 + if ((att&TDbCol::ENotNull)==aNotNull)
1.368 + {
1.369 + SetColumnL(*anIter,*iter,aFlag);
1.370 + ++anIter;
1.371 + }
1.372 + }
1.373 + return anIter;
1.374 + }
1.375 +
1.376 +CDbStoreDef::CDbStoreDef()
1.377 + {}
1.378 +
1.379 +CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,TInt aColumnCount)
1.380 + {
1.381 + CDbStoreDef* self=new(ELeave) CDbStoreDef;
1.382 + CleanupStack::PushL(self);
1.383 + self->ConstructL(aName,aColumnCount);
1.384 + return self;
1.385 + }
1.386 +
1.387 +CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,const CDbColSet& aColSet)
1.388 +//
1.389 +// Construct a table definition from the column set supplied
1.390 +//
1.391 + {
1.392 + CDbStoreDef* self=NewLC(aName,aColSet.Count());
1.393 + HDbColumnSet& columns=self->Columns();
1.394 + HDbColumnSet::TIterator def=CheckColumnsL(columns.Begin(),aColSet,TDbCol::ENotNull);
1.395 + def=CheckColumnsL(def,aColSet,0);
1.396 + __ASSERT(def==columns.End());
1.397 + TRecordSize::CheckSizeL(columns);
1.398 + self->Changed();
1.399 + return self;
1.400 + }
1.401 +
1.402 +CDbStoreDef* CDbStoreDef::NewL(RReadStream& aStream)
1.403 +//
1.404 +// Construct a table definition from persistent storage
1.405 +//
1.406 + {
1.407 + TDbName name;
1.408 + aStream>>name;
1.409 + TCardinality count;
1.410 + aStream>>count;
1.411 + CDbStoreDef* self=NewLC(name,count);
1.412 + HDbColumnSet& columns=self->Columns();
1.413 + HDbColumnSet::TIterator iter=columns.Begin();
1.414 + const HDbColumnSet::TIteratorC end=columns.End();
1.415 + do
1.416 + {
1.417 + aStream>>*iter;
1.418 + } while (++iter<end);
1.419 + aStream>>count;
1.420 + TInt cluster=count;
1.421 + if (cluster==0 || cluster>KMaxClustering)
1.422 + __LEAVE(KErrCorrupt);
1.423 + aStream>>self->iTokenId;
1.424 + RDbIndexes& indexes=self->Indexes();
1.425 + aStream>>count;
1.426 + for (TInt ii=count;ii>0;--ii)
1.427 + indexes.Add(CDbStoreIndexDef::NewL(aStream));
1.428 + self->Changed();
1.429 + CleanupStack::Pop();
1.430 + return self;
1.431 + }
1.432 +
1.433 +void CDbStoreDef::Changed()
1.434 +//
1.435 +// The definition has changed, following creation or alteration of the table
1.436 +// Recalculate cached data for the definition.
1.437 +//
1.438 + {
1.439 + CDbTableDef::Changed();
1.440 + __DEBUG(TBool dbg =)iInfo.Set(Columns());
1.441 + __ASSERT(!dbg);
1.442 + }
1.443 +
1.444 +void CDbStoreDef::ExternalizeL(RWriteStream& aStream) const
1.445 + {
1.446 + aStream<<Name();
1.447 + const HDbColumnSet& columns=Columns();
1.448 + aStream<<TCardinality(columns.Count());
1.449 + HDbColumnSet::TIteratorC iter=columns.Begin();
1.450 + const HDbColumnSet::TIteratorC end=columns.End();
1.451 + do
1.452 + {
1.453 + aStream<<*iter;
1.454 + } while (++iter<end);
1.455 + aStream<<TCardinality(Clustering()); // old stuff, not needed
1.456 + aStream<<iTokenId;
1.457 + aStream<<TCardinality(Indexes().Count());
1.458 + TSglQueIterC<CDbStoreIndexDef> ixIter(Indexes().AsQue());
1.459 + for (const CDbStoreIndexDef* def;(def=ixIter++)!=0;)
1.460 + aStream<<*def;
1.461 + }
1.462 +
1.463 +void CDbStoreDef::AlteredColumnSetL(HDbColumnSet& aSet,const CDbColSet& aChange,const CDbColSet& aAdd)
1.464 +//
1.465 +// Generate an altered column set
1.466 +// We can hijack the non-user attribs of the column sets for marking changes
1.467 +//
1.468 + {
1.469 + // add not-null columns to the front
1.470 + HDbColumnSet::TIterator newCol=CheckColumnsL(aSet.Begin(),aAdd,TDbCol::ENotNull,TDbColumnDef::EAdded);
1.471 + // copy current set, minus deleted ones, apply text column length changes
1.472 + TDbColSetIter change(aChange);
1.473 + HDbColumnSet::TIterator col=Columns().Begin();
1.474 + HDbColumnSet::TIteratorC const end=Columns().End();
1.475 + do
1.476 + {
1.477 + TUint flag=col->iFlags;
1.478 + if (flag&TDbColumnDef::EDropped)
1.479 + continue;
1.480 + if (flag&(TDbColumnDef::EChangedType|TDbColumnDef::EChangedLen))
1.481 + {
1.482 + // check allowed changes
1.483 + SetColumnL(*newCol,*change);
1.484 + ++change;
1.485 + if (flag&TDbColumnDef::EChangedType)
1.486 + { // validate type changes (only text->longtext etc)
1.487 + if (!TDbCol::IsLong(newCol->Type()) || newCol->iType-col->iType!=3)
1.488 + __LEAVE(KErrNotSupported);
1.489 + }
1.490 + else
1.491 + {
1.492 + col->iFlags=TUint8(flag&~TDbColumnDef::EChangedLen); // no real changes req'd
1.493 + if (newCol->iMaxLength<col->iMaxLength)
1.494 + __LEAVE(KErrNotSupported); // can only extend columns
1.495 + }
1.496 + }
1.497 + else
1.498 + newCol->SetL(*col);
1.499 + ++newCol;
1.500 + } while (++col<end);
1.501 + // add nullable columns to the end
1.502 + newCol=CheckColumnsL(newCol,aAdd,0,TDbColumnDef::EAdded);
1.503 + __ASSERT(newCol==aSet.End());
1.504 + TRecordSize::CheckSizeL(aSet);
1.505 + }
1.506 +