os/persistentdata/persistentstorage/dbms/pcdbms/ustor/US_SCHMA.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "US_STD.H"
    17 #include "U32STD_DBMS.H"
    18 #include <d32dbmsconstants.h>
    19 
    20 // class TRecordSize
    21 
    22 TUint8 const TRecordSize::FieldSizes[]=
    23 	{
    24 	0,					// EDbColBit
    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
    35 	};
    36 
    37 TBool TRecordSize::Set(const HDbColumnSet& aColumns)
    38 //
    39 // Calculate stats for the record size and shape from the definition
    40 //
    41 	{
    42 	TInt fix=0,null=0,var=0,blob=0;
    43 	HDbColumnSet::TIteratorC const end=aColumns.End();
    44 	HDbColumnSet::TIteratorC col=aColumns.Begin();
    45 	do
    46 		{
    47 		TBool notnull=col->iAttributes&TDbCol::ENotNull;
    48 		if (notnull==0)
    49 			++fix;
    50 		TDbColType type=col->Type();
    51 		__ASSERT(type>=EDbColBit&&type<=EDbColLongBinary);
    52 		if (type==EDbColBit)
    53 			++fix;
    54 		else if (type<=EDbColDateTime)
    55 			{
    56 			TInt bits=FixedFieldSize(type)<<3;
    57 			if (notnull)
    58 				fix+=bits;
    59 			else
    60 				null+=bits;
    61 			}
    62 		else if (type<=EDbColBinary)
    63 			{
    64 			TInt size=col->iMaxLength;
    65 			if (type==EDbColText16)
    66 				size<<=1;
    67 			var+=8+(size<<3);
    68 			}
    69 		else
    70 			++blob;
    71 		} while(++col<end);
    72 //
    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)
    76 		return ETrue;
    77 //
    78 // Assuming a Maximally full record, how much excess space is available for Blobs?
    79 //
    80 	iInlineLimit=KDbMaxInlineBlobSize;
    81 	if (blob)
    82 		{	// use the spare space for extra inlining
    83 		TInt spare=(KDbStoreMaxRecordLength-max);
    84 		TInt inl=spare/blob+KMinInlineLimit-1;
    85 		if (inl<KDbMaxInlineBlobSize)
    86 			iInlineLimit=inl;
    87 		}
    88 //
    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)
    92 //
    93 	TInt average=(fix+(null>>1)+(var>>4)+blob*(1+(16<<3))+7)>>3;
    94 	TInt clustering=KClusterLimit/average;
    95 	if (clustering==0)
    96 		clustering=1;
    97 	else if (clustering>KMaxClustering)
    98 		clustering=KMaxClustering;
    99 	iClustering=clustering;
   100 	return EFalse;
   101 	}
   102 
   103 void TRecordSize::CheckSizeL(const HDbColumnSet& aColumns)
   104 //
   105 // Check that the columns definition is a valid size
   106 //
   107 	{
   108 	TRecordSize size;
   109 	if (size.Set(aColumns))
   110 		__LEAVE(KErrTooBig);
   111 	}
   112 
   113 TInt TRecordSize::InlineLimit(const HDbColumnSet& aColumns)
   114 //
   115 // Evaluate the inline limit for the column set. It is assumed to be valid
   116 //
   117 	{
   118 	TRecordSize size;
   119 	__DEBUG(TBool chk =)size.Set(aColumns);
   120 	__ASSERT(!chk);
   121 	return size.InlineLimit();
   122 	}
   123 
   124 // Streaming column definitions
   125 
   126 LOCAL_C void ExternalizeL(const TDbColumnDef& aCol,RWriteStream& aStream)
   127 	{
   128 	aStream<<*aCol.iName;
   129 	aStream.WriteUint8L(aCol.iType);
   130 	aStream.WriteUint8L(aCol.iAttributes);
   131 	switch (aCol.iType)
   132 		{
   133 	case EDbColBinary:
   134 	case EDbColText8:
   135 	case EDbColText16:
   136 		aStream.WriteUint8L(aCol.iMaxLength);
   137 		break;
   138 	default:
   139 		break;
   140 		}
   141 	}
   142 
   143 LOCAL_C void InternalizeL(TDbColumnDef& aCol,RReadStream& aStream)
   144 	{
   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)
   152 		{
   153 		aCol.iMaxLength=aStream.ReadUint8L();
   154 		if (aCol.iMaxLength==0)
   155 			__LEAVE(KErrCorrupt);
   156 		}
   157 	else
   158 		aCol.iMaxLength=KDbUndefinedLength;
   159 	}
   160 
   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;}
   165 
   166 // Streaming key columns
   167 
   168 LOCAL_C void ExternalizeL(const TDbKeyCol& aKeyCol,RWriteStream& aStream)
   169 	{
   170 	aStream<<aKeyCol.iName;
   171 	aStream.WriteUint8L(aKeyCol.iLength!=KDbUndefinedLength ? aKeyCol.iLength : 0);
   172 	aStream.WriteUint8L(aKeyCol.iOrder);
   173 	}
   174 
   175 LOCAL_C void InternalizeL(TDbKeyCol& aKeyCol,RReadStream& aStream)
   176 	{
   177 	TPtr des=aKeyCol.iName.Des();
   178 	aStream>>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);
   184 	}
   185 
   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;}
   190 
   191 
   192 // Class CDbStoreIndexDef
   193 
   194 CDbStoreIndexDef::CDbStoreIndexDef()
   195 	{}
   196 
   197 CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName)
   198 	{
   199 	CDbStoreIndexDef* self=new(ELeave) CDbStoreIndexDef;
   200 	CleanupStack::PushL(self);
   201 	self->ConstructL(aName);
   202 	return self;
   203 	}
   204 
   205 CDbStoreIndexDef* CDbStoreIndexDef::NewLC(const TDesC& aName,const CDbKey& aKey,const HDbColumnSet& aColumns)
   206 	{
   207 	CDbStoreIndexDef* self=NewLC(aName);
   208 	CDbKey& key=self->Key();
   209 	TInt max=aKey.Count();
   210 	for (TInt ii=0;ii<max;++ii)
   211 		{
   212 		TDbKeyCol kCol=aKey[ii];
   213 		const TDbColumnDef& col=*aColumns.ColumnL(kCol.iName);
   214 		switch (col.iType)
   215 			{
   216 		default:
   217 			break;
   218 		case EDbColText8:
   219 		case EDbColText16:
   220 			if (kCol.iLength==KDbUndefinedLength)
   221 				kCol.iLength=col.iMaxLength;
   222 			break;
   223 		case EDbColLongText8:
   224 		case EDbColLongText16:
   225 			if (kCol.iLength==KDbUndefinedLength)
   226 				__LEAVE(KErrArgument);
   227 			break;
   228 		case EDbColBinary:
   229 		case EDbColLongBinary:
   230 			__LEAVE(KErrArgument);
   231 			break;
   232 			}
   233 		key.AddL(kCol);
   234 		}
   235 	if (aKey.IsUnique())
   236 		key.MakeUnique();
   237 	if (aKey.IsPrimary())
   238 		key.MakePrimary();
   239 	key.SetComparison(aKey.Comparison());
   240 	CheckSizeL(key,aColumns);
   241 	return self;
   242 	}
   243 
   244 CDbStoreIndexDef* CDbStoreIndexDef::NewL(RReadStream& aStream)
   245 //
   246 // Construct an index definition from persistent storage
   247 //
   248 	{
   249 	TDbName name;
   250 	aStream>>name;
   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())
   258 		key.MakeUnique();
   259 	TCardinality count;
   260 	aStream>>count;
   261 	for (TInt ii=count;ii>0;--ii)
   262 		{
   263 		TDbKeyCol keycol;
   264 		aStream>>keycol;
   265 		key.AddL(keycol);
   266 		}
   267 	aStream>>self->iTokenId;
   268 	CleanupStack::Pop();
   269 	return self;
   270 	}
   271 
   272 void CDbStoreIndexDef::ExternalizeL(RWriteStream& aStream) const
   273 	{
   274 	aStream<<Name();
   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)
   281 		aStream<<key[ii];
   282 	aStream<<iTokenId;
   283 	}
   284 
   285 TInt CDbStoreIndexDef::KeySize(const TDbKeyCol& aKeyCol,const TDbColumnDef& aColumn)
   286 	{
   287 	LOCAL_D const TUint8 KFixedSize[]=
   288 		{
   289 		sizeof(TUint32),
   290 		sizeof(TInt32),
   291 		sizeof(TUint32),
   292 		sizeof(TInt32),
   293 		sizeof(TUint32),
   294 		sizeof(TInt32),
   295 		sizeof(TUint32),
   296 		sizeof(TInt64),
   297 		sizeof(TReal32),
   298 		sizeof(TReal64),
   299 		sizeof(TTime)
   300 		};
   301 	TDbColType t=aColumn.Type();
   302 	if (TUint(t)<sizeof(KFixedSize)/sizeof(KFixedSize[0]))
   303 		return KFixedSize[t];
   304 	switch (t)
   305 		{
   306 	default:
   307 		__ASSERT(0);
   308 	case EDbColText8:
   309 	case EDbColLongText8:
   310 		return aKeyCol.iLength;
   311 	case EDbColText16:
   312 	case EDbColLongText16:
   313 		return aKeyCol.iLength<<1;
   314 		}
   315 	}
   316 
   317 void CDbStoreIndexDef::CheckSizeL(const CDbKey& aKey,const HDbColumnSet& aColSet)
   318 //
   319 // Check the size of the key for the index definition
   320 //
   321 	{
   322 	TInt len=aKey.IsUnique()?0:sizeof(TDbRecordId);
   323 	for (TInt ii=aKey.Count();--ii>=0;)
   324 		{
   325 		const TDbKeyCol& keyCol=aKey[ii];
   326 		len+=Align4(KeySize(keyCol,*aColSet.ColumnL(keyCol.iName)));
   327 		}
   328 	if (len>KMaxIndexKeySize)
   329 		__LEAVE(KErrTooBig);
   330 	}
   331 
   332 
   333 // Class CDbStoreDef
   334 
   335 LOCAL_C void SetColumnL(TDbColumnDef& aDef,const TDbCol& aCol,TUint aFlag=0)
   336 	{
   337 	aDef.SetL(aCol);
   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)
   343 		{
   344 		if (aCol.iMaxLength==KDbUndefinedLength)
   345 			aDef.iMaxLength=KDbStoreMaxColumnLength;
   346 		else if (aCol.iMaxLength>KDbStoreMaxColumnLength)
   347 			__LEAVE(KErrNotSupported);
   348 		}
   349 	else
   350 		aDef.iMaxLength=KDbUndefinedLength;
   351 	}
   352 
   353 LOCAL_C HDbColumnSet::TIterator CheckColumnsL(HDbColumnSet::TIterator anIter,const CDbColSet& aColSet,TInt aNotNull,TUint aFlag=0)
   354 //
   355 // Check the columns from aColset into anIter, according to ENotNull attribute
   356 // Validate as we go
   357 //
   358 	{
   359 	for (TDbColSetIter iter(aColSet);iter;++iter)
   360 		{
   361 		TInt att=iter->iAttributes;
   362 		if (att&TDbCol::EAutoIncrement)
   363 			att|=TDbCol::ENotNull;		// auto-increment => not-null
   364 		if ((att&TDbCol::ENotNull)==aNotNull)
   365 			{
   366 			SetColumnL(*anIter,*iter,aFlag);
   367 			++anIter;
   368 			}
   369 		}
   370 	return anIter;
   371 	}
   372 
   373 CDbStoreDef::CDbStoreDef()
   374 	{}
   375 
   376 CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,TInt aColumnCount)
   377 	{
   378 	CDbStoreDef* self=new(ELeave) CDbStoreDef;
   379 	CleanupStack::PushL(self);
   380 	self->ConstructL(aName,aColumnCount);
   381 	return self;
   382 	}
   383 
   384 CDbStoreDef* CDbStoreDef::NewLC(const TDesC& aName,const CDbColSet& aColSet)
   385 //
   386 // Construct a table definition from the column set supplied
   387 //
   388 	{
   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);
   395 	self->Changed();
   396 	return self;
   397 	}
   398 
   399 CDbStoreDef* CDbStoreDef::NewL(RReadStream& aStream)
   400 //
   401 // Construct a table definition from persistent storage
   402 //
   403 	{
   404 	TDbName name;
   405 	aStream>>name;
   406 	TCardinality count;
   407 	aStream>>count;
   408 	CDbStoreDef* self=NewLC(name,count);
   409 	HDbColumnSet& columns=self->Columns();
   410 	HDbColumnSet::TIterator iter=columns.Begin();
   411 	const HDbColumnSet::TIteratorC end=columns.End();
   412 	do
   413 		{
   414 		aStream>>*iter;
   415 		} while (++iter<end);
   416 	aStream>>count;
   417 	TInt cluster=count;
   418 	if (cluster==0 || cluster>KMaxClustering)
   419 		__LEAVE(KErrCorrupt);
   420 	aStream>>self->iTokenId;
   421 	RDbIndexes& indexes=self->Indexes();
   422 	aStream>>count;
   423 	for (TInt ii=count;ii>0;--ii)
   424 		indexes.Add(CDbStoreIndexDef::NewL(aStream));
   425 	self->Changed();
   426 	CleanupStack::Pop();
   427 	return self;
   428 	}
   429 
   430 void CDbStoreDef::Changed()
   431 //
   432 // The definition has changed, following creation or alteration of the table
   433 // Recalculate cached data for the definition.
   434 //
   435 	{
   436 	CDbTableDef::Changed();
   437 	__DEBUG(TBool dbg =)iInfo.Set(Columns());
   438 	__ASSERT(!dbg);
   439 	}
   440 
   441 void CDbStoreDef::ExternalizeL(RWriteStream& aStream) const
   442 	{
   443 	aStream<<Name();
   444 	const HDbColumnSet& columns=Columns();
   445 	aStream<<TCardinality(columns.Count());
   446 	HDbColumnSet::TIteratorC iter=columns.Begin();
   447 	const HDbColumnSet::TIteratorC end=columns.End();
   448 	do
   449 		{
   450 		aStream<<*iter;
   451 		} while (++iter<end);
   452 	aStream<<TCardinality(Clustering());	// old stuff, not needed
   453 	aStream<<iTokenId;
   454 	aStream<<TCardinality(Indexes().Count());
   455 	TSglQueIterC<CDbStoreIndexDef> ixIter(Indexes().AsQue());
   456 	for (const CDbStoreIndexDef* def;(def=ixIter++)!=0;)
   457 		aStream<<*def;
   458 	}
   459 
   460 void CDbStoreDef::AlteredColumnSetL(HDbColumnSet& aSet,const CDbColSet& aChange,const CDbColSet& aAdd)
   461 //
   462 // Generate an altered column set
   463 // We can hijack the non-user attribs of the column sets for marking changes
   464 //
   465 	{
   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();
   472 	do
   473 		{
   474 		TUint flag=col->iFlags;
   475 		if (flag&TDbColumnDef::EDropped)
   476 			continue;
   477 		if (flag&(TDbColumnDef::EChangedType|TDbColumnDef::EChangedLen))
   478 			{
   479 			// check allowed changes
   480 			SetColumnL(*newCol,*change);
   481 			++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);
   486 				}
   487 			else
   488 				{
   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
   492 				}
   493 			}
   494 		else
   495 			newCol->SetL(*col);
   496 		++newCol;
   497 		} while (++col<end);
   498 	// add nullable columns to the end
   499 	newCol=CheckColumnsL(newCol,aAdd,0,TDbColumnDef::EAdded);
   500 	__ASSERT(newCol==aSet.End());
   501 	TRecordSize::CheckSizeL(aSet);
   502 	}
   503