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