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