os/persistentdata/persistentstorage/dbms/ustor/US_DBS.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
sl@0
    18
// Class CDbStoreDatabase::CCompactor
sl@0
    19
sl@0
    20
NONSHARABLE_CLASS(CDbStoreDatabase::CCompactor) : public CDbStoreDatabase::CStepper
sl@0
    21
	{
sl@0
    22
public:
sl@0
    23
	static CCompactor* NewL(CDbDatabase::TUtility aType, CStreamStore& aStore,
sl@0
    24
                            TInt& aReclaim, TInt& aStep);
sl@0
    25
	~CCompactor();
sl@0
    26
private:
sl@0
    27
	inline CCompactor(TInt& aReclaim);
sl@0
    28
// from CStepper
sl@0
    29
	TInt StepL(TInt aStep);
sl@0
    30
private:
sl@0
    31
	RStoreReclaim iReclaimer;
sl@0
    32
	TInt& iReclaim;
sl@0
    33
	};
sl@0
    34
sl@0
    35
inline CDbStoreDatabase::CCompactor::CCompactor(TInt& aReclaim)
sl@0
    36
	:iReclaim(aReclaim)
sl@0
    37
	{
sl@0
    38
	}
sl@0
    39
sl@0
    40
CDbStoreDatabase::CCompactor* CDbStoreDatabase::CCompactor::NewL(CDbDatabase::TUtility aType,
sl@0
    41
																 CStreamStore& aStore,
sl@0
    42
																 TInt& aReclaim,TInt& aStep)
sl@0
    43
	{
sl@0
    44
	CCompactor* self=new(ELeave) CCompactor(aReclaim);
sl@0
    45
	CleanupStack::PushL(self);
sl@0
    46
	if (aType==CDbDatabase::ECompact)
sl@0
    47
		self->iReclaimer.CompactL(aStore,aStep);
sl@0
    48
	else
sl@0
    49
		self->iReclaimer.OpenL(aStore,aStep);
sl@0
    50
	CleanupStack::Pop();
sl@0
    51
	return self;
sl@0
    52
	}
sl@0
    53
sl@0
    54
CDbStoreDatabase::CCompactor::~CCompactor()
sl@0
    55
	{
sl@0
    56
	iReclaimer.Close();
sl@0
    57
	}
sl@0
    58
sl@0
    59
//
sl@0
    60
// Single step the compactor
sl@0
    61
// We cannot deal with the "in use" scenario as we could end up locking out forever
sl@0
    62
// that has to be left to clients using the RDbIncremental interface
sl@0
    63
//
sl@0
    64
TInt CDbStoreDatabase::CCompactor::StepL(TInt aStep)
sl@0
    65
	{
sl@0
    66
	iReclaimer.NextL(aStep);
sl@0
    67
	if (aStep==0)
sl@0
    68
		{
sl@0
    69
		iReclaim=iReclaimer.Available();
sl@0
    70
		iReclaimer.Close();
sl@0
    71
		}
sl@0
    72
	return aStep;
sl@0
    73
	}
sl@0
    74
sl@0
    75
sl@0
    76
// Class CDbStoreDatabase
sl@0
    77
sl@0
    78
EXPORT_C CDbStoreDatabase::CDbStoreDatabase()
sl@0
    79
	:iReclaim(KErrGeneral)
sl@0
    80
	{
sl@0
    81
	}
sl@0
    82
sl@0
    83
//
sl@0
    84
// Create a StoreDatabase object. This type shares the store
sl@0
    85
//
sl@0
    86
CDbStoreDatabase* CDbStoreDatabase::NewLC(CStreamStore* aStore)
sl@0
    87
	{
sl@0
    88
	__ASSERT(aStore);
sl@0
    89
	CDbStoreDatabase* self=new(ELeave) CDbStoreDatabase;
sl@0
    90
	CleanupStack::PushL(self);
sl@0
    91
	self->iStore=aStore;
sl@0
    92
	self->iSharedStore=1;
sl@0
    93
	return self;
sl@0
    94
	}
sl@0
    95
sl@0
    96
sl@0
    97
//SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
sl@0
    98
CDbDatabase* CDbStoreDatabase::CreateL(CStreamStore* aStore,TStreamId& aStreamId)
sl@0
    99
	{
sl@0
   100
	CDbStoreDatabase* self=NewLC(aStore);
sl@0
   101
	aStreamId=self->ConstructL();
sl@0
   102
	CDbDatabase* db=self->InterfaceL();
sl@0
   103
	CleanupStack::Pop();			// self
sl@0
   104
	return db;
sl@0
   105
	}
sl@0
   106
	
sl@0
   107
// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
sl@0
   108
// Phase 2 construction for creating a new database
sl@0
   109
// Initialise a new database object, creating the required persistent structure
sl@0
   110
//
sl@0
   111
EXPORT_C TStreamId CDbStoreDatabase::ConstructL()
sl@0
   112
	{
sl@0
   113
	__ASSERT(iStore);	// this must have been provided by now
sl@0
   114
	iVersion=TUint8(EDbStoreVersion2);
sl@0
   115
	InitPagePoolL();
sl@0
   116
	iPagePool->Create(Store());
sl@0
   117
	iTokenId=Store().ExtendL();
sl@0
   118
	ReplaceTokenL(0);
sl@0
   119
	iSchemaId=Store().ExtendL();
sl@0
   120
	Schema().Loaded();
sl@0
   121
	ReplaceSchemaL();
sl@0
   122
	return iSchemaId;
sl@0
   123
	}
sl@0
   124
	
sl@0
   125
// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
sl@0
   126
// Open phase #2: Authenticate the client
sl@0
   127
//
sl@0
   128
EXPORT_C void CDbStoreDatabase::AuthenticateL()
sl@0
   129
	{
sl@0
   130
	if (!iPagePool)
sl@0
   131
		{
sl@0
   132
		// first client to open the database, so complete initialisation now
sl@0
   133
		InitPagePoolL();
sl@0
   134
		SchemaL();
sl@0
   135
		}
sl@0
   136
	}
sl@0
   137
sl@0
   138
// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
sl@0
   139
void CDbStoreDatabase::InitPagePoolL()
sl@0
   140
	{
sl@0
   141
	iPagePool = new(ELeave) RStorePagePool;
sl@0
   142
	}
sl@0
   143
	
sl@0
   144
sl@0
   145
CDbSource* CDbStoreDatabase::OpenL(CStreamStore* aStore,TStreamId aStreamId)
sl@0
   146
	{
sl@0
   147
	CDbStoreDatabase* self=NewLC(aStore);
sl@0
   148
	self->RestoreL(aStreamId);
sl@0
   149
	CDbSource* src=self->SourceL();
sl@0
   150
	CleanupStack::Pop();			// self
sl@0
   151
	return src;
sl@0
   152
	}
sl@0
   153
sl@0
   154
//
sl@0
   155
// Phase 2 construction for opening a database
sl@0
   156
// Client must still authenticate before it can be used
sl@0
   157
//
sl@0
   158
EXPORT_C void CDbStoreDatabase::RestoreL(TStreamId aStreamId)
sl@0
   159
	{
sl@0
   160
	__ASSERT(iStore);	// this must have been provided by now
sl@0
   161
	iSchemaId=aStreamId;
sl@0
   162
// read the databse header for encryption information
sl@0
   163
	RStoreReadStream strm;
sl@0
   164
	strm.OpenLC(Store(),aStreamId);
sl@0
   165
	ReadHeaderL(strm);
sl@0
   166
	CleanupStack::PopAndDestroy();	// strm
sl@0
   167
	}
sl@0
   168
sl@0
   169
//
sl@0
   170
// Load the root stream header (up to the security key)
sl@0
   171
//
sl@0
   172
void CDbStoreDatabase::ReadHeaderL(RReadStream& aStream)
sl@0
   173
	{
sl@0
   174
	TUid uid;
sl@0
   175
	aStream>>uid;
sl@0
   176
	if (uid!=KDbmsStoreDatabase)
sl@0
   177
		__LEAVE(KErrArgument);
sl@0
   178
	aStream>>iVersion;
sl@0
   179
	switch (iVersion)
sl@0
   180
		{
sl@0
   181
	case EDbStoreCompressed:
sl@0
   182
		aStream>>CompressionL();
sl@0
   183
		break;
sl@0
   184
	case EDbStoreVersion2:
sl@0
   185
		break;
sl@0
   186
	default:
sl@0
   187
		__LEAVE(KErrNotSupported);
sl@0
   188
		break;
sl@0
   189
		}
sl@0
   190
	}
sl@0
   191
sl@0
   192
CDbStoreCompression& CDbStoreDatabase::CompressionL()
sl@0
   193
	{
sl@0
   194
	CDbStoreCompression* c=iCompression;
sl@0
   195
	if (!c)
sl@0
   196
		iFilter=iCompression=c=CDbStoreCompression::NewL();
sl@0
   197
	return *c;
sl@0
   198
	}
sl@0
   199
sl@0
   200
EXPORT_C CDbStoreDatabase::~CDbStoreDatabase()
sl@0
   201
	{
sl@0
   202
	if (iPageCache)
sl@0
   203
		{
sl@0
   204
		iPagePool->Release();
sl@0
   205
		delete iPageCache;
sl@0
   206
		}
sl@0
   207
	delete iClusterCache;
sl@0
   208
	delete iPagePool;
sl@0
   209
	delete iCompression;
sl@0
   210
	if (!iSharedStore)
sl@0
   211
		delete iStore;
sl@0
   212
	}
sl@0
   213
sl@0
   214
//
sl@0
   215
// Validate the column set first
sl@0
   216
//
sl@0
   217
EXPORT_C CDbTableDef* CDbStoreDatabase::CreateTableL(const TDesC& aName,const CDbColSet& aColSet,const CDbKey* aPrimaryKey)
sl@0
   218
	{
sl@0
   219
	if (aPrimaryKey)
sl@0
   220
		__LEAVE(KErrNotSupported);	// Store database does not support primary keys
sl@0
   221
	CDbStoreDef* def=CDbStoreDef::NewLC(aName,aColSet);
sl@0
   222
	def->SetTokenId(CDbStoreRecords::CreateL(ClusterCacheL()));
sl@0
   223
	CleanupStack::Pop();
sl@0
   224
	return def;
sl@0
   225
	}
sl@0
   226
sl@0
   227
EXPORT_C CDbTableIndexDef* CDbStoreDatabase::CreateIndexL(const CDbTableDef& aTable,const TDesC& aName,const CDbKey& aKey)
sl@0
   228
	{
sl@0
   229
	CDbStoreIndexDef* def=CDbStoreIndexDef::NewLC(aName,aKey,aTable.Columns());
sl@0
   230
	def->SetTokenId(CDbStoreIndex::CreateL(*this,*def));
sl@0
   231
	CleanupStack::Pop();			// IndexDef
sl@0
   232
	return def;
sl@0
   233
	}
sl@0
   234
sl@0
   235
//
sl@0
   236
// Destroy the entire database...
sl@0
   237
//
sl@0
   238
EXPORT_C void CDbStoreDatabase::DestroyL()
sl@0
   239
	{
sl@0
   240
	iPagePool->Discard();
sl@0
   241
	iPagePool->ReclaimAllL();	// reclaim all page pool space
sl@0
   242
	iStore->DeleteL(iSchemaId);
sl@0
   243
	iStore->DeleteL(iTokenId);
sl@0
   244
	iStore->CommitL();
sl@0
   245
	}
sl@0
   246
sl@0
   247
EXPORT_C CDbTable* CDbStoreDatabase::TableL(const CDbTableDef& aDef)
sl@0
   248
	{
sl@0
   249
	return new(ELeave) CDbStoreTable(*this,aDef);
sl@0
   250
	}
sl@0
   251
sl@0
   252
//
sl@0
   253
// load the schema for the database
sl@0
   254
//
sl@0
   255
EXPORT_C void CDbStoreDatabase::LoadSchemaL()
sl@0
   256
	{
sl@0
   257
	RDbStoreReadStream strm(*this);
sl@0
   258
	strm.OpenLC(Store(),iSchemaId);
sl@0
   259
	ReadHeaderL(strm);
sl@0
   260
	strm.FilterL(strm.EMixed,iSchemaId.Value());
sl@0
   261
	strm>>iTokenId;
sl@0
   262
	RDbTableSchema& schema=Schema();
sl@0
   263
	TCardinality tables;
sl@0
   264
	strm>>tables;
sl@0
   265
	for (TInt ii=tables;ii>0;--ii)
sl@0
   266
		schema.Add(CDbStoreDef::NewL(strm));
sl@0
   267
	CleanupStack::PopAndDestroy();
sl@0
   268
	strm.OpenLC(Store(),iTokenId);
sl@0
   269
	strm>>iFlags>>iPoolToken;
sl@0
   270
	iPagePool->Open(Store(),iPoolToken);
sl@0
   271
	CleanupStack::PopAndDestroy();
sl@0
   272
	}
sl@0
   273
sl@0
   274
//
sl@0
   275
// Re-write the schema stream
sl@0
   276
//
sl@0
   277
void CDbStoreDatabase::ReplaceSchemaL()
sl@0
   278
	{
sl@0
   279
	RDbStoreWriteStream out(*this);
sl@0
   280
	out.ReplaceLC(Store(),iSchemaId);
sl@0
   281
	out<<KDbmsStoreDatabase<<iVersion;
sl@0
   282
	switch (iVersion)
sl@0
   283
		{
sl@0
   284
	case EDbStoreCompressed:
sl@0
   285
		__ASSERT(iCompression);
sl@0
   286
		out<<*iCompression;
sl@0
   287
		break;
sl@0
   288
	case EDbStoreVersion2:
sl@0
   289
		break;
sl@0
   290
	default:
sl@0
   291
		__ASSERT(0);
sl@0
   292
		}
sl@0
   293
	out.FilterL(out.EMixed,iSchemaId.Value());
sl@0
   294
	out<<iTokenId;
sl@0
   295
	TSglQueIterC<CDbStoreDef> iter(Schema());
sl@0
   296
	TInt count=0;
sl@0
   297
	while (iter++)
sl@0
   298
		++count;
sl@0
   299
	out<<TCardinality(count);
sl@0
   300
	iter.SetToFirst();
sl@0
   301
	for (const CDbStoreDef* def;(def=iter++)!=0;)
sl@0
   302
		out<<*def;
sl@0
   303
	out.CommitL();
sl@0
   304
	CleanupStack::PopAndDestroy();
sl@0
   305
	}
sl@0
   306
sl@0
   307
//
sl@0
   308
// Re-write the token stream, removing the mark
sl@0
   309
//
sl@0
   310
void CDbStoreDatabase::ReplaceTokenL(TUint aFlags)
sl@0
   311
	{
sl@0
   312
	RStoreWriteStream out;
sl@0
   313
	out.ReplaceLC(Store(),iTokenId);
sl@0
   314
	out<<TUint8(aFlags&EDamaged)<<iPagePool->Token();
sl@0
   315
	out.CommitL();
sl@0
   316
	CleanupStack::PopAndDestroy();
sl@0
   317
	}
sl@0
   318
sl@0
   319
//
sl@0
   320
// Return some database property
sl@0
   321
//
sl@0
   322
EXPORT_C TInt CDbStoreDatabase::Property(CDbDatabase::TProperty aProperty)
sl@0
   323
	{
sl@0
   324
	switch (aProperty)
sl@0
   325
		{
sl@0
   326
	case CDbDatabase::EIsDamaged:
sl@0
   327
		return iFlags&EDamaged ? 1 : 0;
sl@0
   328
	case CDbDatabase::ECompactable:
sl@0
   329
		return 1;
sl@0
   330
	default:
sl@0
   331
		return CDbTableDatabase::Property(aProperty);
sl@0
   332
		}
sl@0
   333
	}
sl@0
   334
sl@0
   335
//
sl@0
   336
// mark the database as dirty
sl@0
   337
//
sl@0
   338
void CDbStoreDatabase::MarkL()
sl@0
   339
	{
sl@0
   340
	if (!(iFlags&EModified))
sl@0
   341
		{
sl@0
   342
		RStoreWriteStream out;
sl@0
   343
		out.OpenLC(Store(),iTokenId);
sl@0
   344
		out.WriteUint8L(EDamaged);		// mark as dirty
sl@0
   345
		iPoolToken.Touch();
sl@0
   346
		out<<iPoolToken;
sl@0
   347
		out.CommitL();
sl@0
   348
		CleanupStack::PopAndDestroy();
sl@0
   349
		iFlags|=EModified;
sl@0
   350
		}
sl@0
   351
	}
sl@0
   352
sl@0
   353
//
sl@0
   354
// Reset all cache buffers
sl@0
   355
//
sl@0
   356
EXPORT_C void CDbStoreDatabase::Idle()
sl@0
   357
	{
sl@0
   358
	if (iPageCache)
sl@0
   359
		{
sl@0
   360
		iPagePool->Purge();
sl@0
   361
		delete iPageCache;
sl@0
   362
		iPageCache=NULL;
sl@0
   363
		}
sl@0
   364
	if (iClusterCache)
sl@0
   365
		{
sl@0
   366
		delete iClusterCache;
sl@0
   367
		iClusterCache=NULL;
sl@0
   368
		}
sl@0
   369
	}
sl@0
   370
sl@0
   371
//
sl@0
   372
// Commit the store, and when all is well, clear the token
sl@0
   373
//
sl@0
   374
void CDbStoreDatabase::SynchStoreL(TDbLockType aLock)
sl@0
   375
	{
sl@0
   376
	if (iPageCache)
sl@0
   377
		iPagePool->FlushL();
sl@0
   378
	TUint newflags=iFlags&~EModified;
sl@0
   379
	if (aLock==EDbRecoveryLock)
sl@0
   380
		newflags&=~EDamaged;
sl@0
   381
	if (aLock==EDbRecoveryLock || iFlags&EModified)
sl@0
   382
		ReplaceTokenL(newflags);
sl@0
   383
	if (aLock>=EDbWriteLock || iSharedStore)
sl@0
   384
		{
sl@0
   385
		iStore->CommitL();
sl@0
   386
		iFlags=TUint8(newflags);
sl@0
   387
		iPoolToken=iPagePool->Token();
sl@0
   388
		}
sl@0
   389
	}
sl@0
   390
sl@0
   391
//
sl@0
   392
// An index has been successfully recovered, commit it
sl@0
   393
//
sl@0
   394
void CDbStoreDatabase::IndexRecoveredL()
sl@0
   395
	{
sl@0
   396
	SynchStoreL(EDbSchemaLock);
sl@0
   397
	}
sl@0
   398
sl@0
   399
//
sl@0
   400
// Ensure all data is in the store
sl@0
   401
//
sl@0
   402
EXPORT_C void CDbStoreDatabase::SynchL(TDbLockType aLock)
sl@0
   403
	{
sl@0
   404
	if (aLock==EDbSchemaLock)
sl@0
   405
		ReplaceSchemaL();
sl@0
   406
	if (iClusterCache)
sl@0
   407
		iClusterCache->FlushL();
sl@0
   408
	SynchStoreL(aLock);
sl@0
   409
	}
sl@0
   410
sl@0
   411
//
sl@0
   412
// Unwind the store, throw out changes, etc
sl@0
   413
//
sl@0
   414
EXPORT_C void CDbStoreDatabase::Revert(TDbLockType aLock)
sl@0
   415
	{
sl@0
   416
	if (aLock>=EDbWriteLock)
sl@0
   417
		{
sl@0
   418
		if (iClusterCache)
sl@0
   419
			iClusterCache->Discard();
sl@0
   420
		if (iPageCache)
sl@0
   421
			iPagePool->Purge();
sl@0
   422
		if (iFlags&EModified)
sl@0
   423
			iFlags|=EDamaged;
sl@0
   424
		iPagePool->Open(Store(),iPoolToken);	// reset the page pool
sl@0
   425
		}
sl@0
   426
	else if (!iSharedStore)		// don't touch the store if not shared
sl@0
   427
		return;
sl@0
   428
	iStore->Revert();
sl@0
   429
	}
sl@0
   430
sl@0
   431
//
sl@0
   432
// Ensure we have a cluster cache and return it
sl@0
   433
//
sl@0
   434
CClusterCache& CDbStoreDatabase::ClusterCacheL()
sl@0
   435
	{
sl@0
   436
	CClusterCache* cache=iClusterCache;
sl@0
   437
	if (!cache)
sl@0
   438
		iClusterCache=cache=CClusterCache::NewL(*this);
sl@0
   439
	return *cache;
sl@0
   440
	}
sl@0
   441
sl@0
   442
//
sl@0
   443
// Ensure we have a page cache and return the pool
sl@0
   444
//
sl@0
   445
MPagePool& CDbStoreDatabase::PagePoolL()
sl@0
   446
	{
sl@0
   447
	if (!iPageCache)
sl@0
   448
		{
sl@0
   449
		iPageCache=CPageCache::NewL(EPageCachePages);
sl@0
   450
		iPagePool->Set(*iPageCache);
sl@0
   451
		}
sl@0
   452
	return *iPagePool;
sl@0
   453
	}
sl@0
   454
sl@0
   455
//
sl@0
   456
// Create an incremental object that compacts the store
sl@0
   457
//
sl@0
   458
EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::UtilityL(CDbDatabase::TUtility aType,TInt& aStep)
sl@0
   459
	{
sl@0
   460
	switch (aType)
sl@0
   461
		{
sl@0
   462
	case CDbDatabase::EStats:
sl@0
   463
	case CDbDatabase::ECompact:
sl@0
   464
		return CCompactor::NewL(aType,Store(),iReclaim,aStep);
sl@0
   465
	case CDbDatabase::ERecover:
sl@0
   466
		return RecoverL(aStep);
sl@0
   467
	default:
sl@0
   468
		return CDbTableDatabase::UtilityL(aType,aStep);
sl@0
   469
		}
sl@0
   470
	}
sl@0
   471
sl@0
   472
//
sl@0
   473
// Create an incremental object to destroy a table
sl@0
   474
//
sl@0
   475
EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::RecordDiscarderL(const CDbTableDef& aTable,TInt& aStep)
sl@0
   476
	{
sl@0
   477
	CDbStoreTable::CDiscarder* discarder=new(ELeave) CDbStoreTable::CDiscarder;
sl@0
   478
	CleanupStack::PushL(discarder);
sl@0
   479
	aStep=discarder->OpenL((CDbStoreTable*)TableL(aTable));
sl@0
   480
	CleanupStack::Pop();
sl@0
   481
	return discarder;
sl@0
   482
	}
sl@0
   483
sl@0
   484
//
sl@0
   485
// Create an incremental object to destroy an index
sl@0
   486
//
sl@0
   487
EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::IndexDiscarderL(const CDbTableDef& aTable,const CDbTableIndexDef& anIndex,TInt& aStep)
sl@0
   488
	{
sl@0
   489
	CDbStoreIndex::CDiscarder* discarder=new(ELeave) CDbStoreIndex::CDiscarder;
sl@0
   490
	CleanupStack::PushL(discarder);
sl@0
   491
	CDbStoreIndex* index=CDbStoreIndex::NewL(*this,(const CDbStoreIndexDef&)anIndex,aTable);
sl@0
   492
	aStep=discarder->Open(index);
sl@0
   493
	index->OpenL();
sl@0
   494
	CleanupStack::Pop();
sl@0
   495
	return discarder;
sl@0
   496
	}
sl@0
   497
sl@0
   498
//
sl@0
   499
// Provide a stepper to alter the table data
sl@0
   500
// if no data to alter, return 0
sl@0
   501
//
sl@0
   502
EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::TableAlterL(CDbTableDef& aTable,const HDbColumnSet& aNewSet,TInt& aStep)
sl@0
   503
	{
sl@0
   504
	CDbStoreDef& def=STATIC_CAST(CDbStoreDef&,aTable);
sl@0
   505
//
sl@0
   506
	aStep=CDbStoreRecords::CardinalityL(Store(),def);
sl@0
   507
	if (!aStep)
sl@0
   508
		return NULL; // no data to modify
sl@0
   509
sl@0
   510
// check that all added columns are nullable
sl@0
   511
	HDbColumnSet::TIteratorC col=aNewSet.Begin();
sl@0
   512
	HDbColumnSet::TIteratorC end=aNewSet.End();
sl@0
   513
	do
sl@0
   514
		{
sl@0
   515
		if (col->iFlags&TDbColumnDef::EAdded && col->iAttributes&TDbCol::ENotNull)
sl@0
   516
			__LEAVE(KErrArgument);		// added column is not nullable
sl@0
   517
		} while (++col<end);
sl@0
   518
//
sl@0
   519
// check to see if anything is being dropped or changed type
sl@0
   520
	col=aTable.Columns().Begin();
sl@0
   521
	end=aTable.Columns().End();
sl@0
   522
	while (!(col->iFlags&(TDbColumnDef::EDropped|TDbColumnDef::EChangedType|TDbColumnDef::EChangedLen)))
sl@0
   523
		{
sl@0
   524
		if (++col==end)
sl@0
   525
			{	// no changes which affect layout, so no work required
sl@0
   526
			aStep=0;
sl@0
   527
			return NULL;
sl@0
   528
			}
sl@0
   529
		}
sl@0
   530
// work required
sl@0
   531
	CDbStoreTable::CAlter* alter=new(ELeave) CDbStoreTable::CAlter;
sl@0
   532
	CleanupStack::PushL(alter);
sl@0
   533
	alter->OpenL((CDbStoreTable*)TableL(def),aNewSet);
sl@0
   534
	CleanupStack::Pop();
sl@0
   535
	return alter;
sl@0
   536
	}
sl@0
   537
sl@0
   538
EXPORT_C void CDbStoreDatabase::Reserved_1()
sl@0
   539
	{
sl@0
   540
	}
sl@0
   541
sl@0
   542
EXPORT_C void CDbStoreDatabase::Reserved_2()
sl@0
   543
	{
sl@0
   544
	}
sl@0
   545