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