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