os/persistentdata/persistentstorage/dbms/pcdbms/utable/UT_INCR.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
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 "UT_STD.H"
sl@0
    17
#include "U32STD_DBMS.H"
sl@0
    18
// Class CDbTableDatabase::CMultiStepper
sl@0
    19
sl@0
    20
inline CDbTableDatabase::CMultiStepper::CMultiStepper( TInt aCount )
sl@0
    21
 :	iStepper( iSteppers - 1 ), iEnd( iSteppers + aCount )
sl@0
    22
	{}
sl@0
    23
sl@0
    24
CDbTableDatabase::CMultiStepper::~CMultiStepper()
sl@0
    25
	{
sl@0
    26
	SStepper* const end = iEnd;
sl@0
    27
	for ( SStepper* iter = iSteppers; iter < end; ++iter )
sl@0
    28
		delete iter->iStepper;
sl@0
    29
	}
sl@0
    30
sl@0
    31
EXPORT_C CDbTableDatabase::CMultiStepper* CDbTableDatabase::CMultiStepper::NewL( TInt aStepperCount )
sl@0
    32
	{
sl@0
    33
	return new( ELeave, sizeof( SStepper ) * ( aStepperCount - 1 ) ) CMultiStepper( aStepperCount );	// get the extra size for the entries, leaves on error
sl@0
    34
	}
sl@0
    35
sl@0
    36
EXPORT_C void CDbTableDatabase::CMultiStepper::AddStepper( CStepper* aStepper, TInt aStep )
sl@0
    37
	{
sl@0
    38
	++iStepper;
sl@0
    39
	__ASSERT( iStepper < iEnd );
sl@0
    40
	iStepper->iStepper = aStepper;
sl@0
    41
	iStepper->iStep = aStep;
sl@0
    42
	}
sl@0
    43
sl@0
    44
EXPORT_C TInt CDbTableDatabase::CMultiStepper::TotalSteps()
sl@0
    45
//
sl@0
    46
// Count the number of steps, and normalise the step counts
sl@0
    47
//
sl@0
    48
	{
sl@0
    49
	TInt steps = 0;
sl@0
    50
	SStepper* const end = iStepper;
sl@0
    51
	for( SStepper* stepper = iSteppers; stepper <= end; ++stepper )
sl@0
    52
		{
sl@0
    53
		TInt step = stepper->iStep;
sl@0
    54
		stepper->iStep = steps;
sl@0
    55
		steps += step;
sl@0
    56
		}
sl@0
    57
	return steps;
sl@0
    58
	}
sl@0
    59
sl@0
    60
TInt CDbTableDatabase::CMultiStepper::StepL( TInt aStep )
sl@0
    61
	{
sl@0
    62
	SStepper* stepper = iStepper;
sl@0
    63
	__ASSERT( stepper != 0 && stepper >= iSteppers );
sl@0
    64
	TInt base;
sl@0
    65
	for ( ; ; )
sl@0
    66
		{
sl@0
    67
		base = stepper->iStep;
sl@0
    68
		if ( aStep > base )
sl@0
    69
			break;
sl@0
    70
		if ( --stepper < iSteppers )
sl@0
    71
			return 0;
sl@0
    72
		iStepper = stepper;
sl@0
    73
		}
sl@0
    74
	return stepper->iStepper->StepL( aStep - base ) + base;
sl@0
    75
	}
sl@0
    76
sl@0
    77
// Class CDbTableDatabase::CIncremental
sl@0
    78
sl@0
    79
CDbTableDatabase::CIncremental::CIncremental(RDbTransaction& aTransaction)
sl@0
    80
	: iTransaction(aTransaction)
sl@0
    81
	{
sl@0
    82
	Database().Open();		// we reference the database
sl@0
    83
	__ASSERT(iState==ERunning);
sl@0
    84
	}
sl@0
    85
sl@0
    86
CDbTableDatabase::CIncremental::~CIncremental()
sl@0
    87
	{
sl@0
    88
	delete iStepper;
sl@0
    89
	Database().Close();		// drop the database reference
sl@0
    90
	}
sl@0
    91
sl@0
    92
TBool CDbTableDatabase::CIncremental::NextL(TInt& aStep)
sl@0
    93
//
sl@0
    94
// if step is 1 then invopke the last step otherwise do
sl@0
    95
//
sl@0
    96
	{
sl@0
    97
	__ASSERT(!IsCommitted());
sl@0
    98
	if (iState==EFailed)
sl@0
    99
		__LEAVE(KErrDied);
sl@0
   100
	iState=EFailed;
sl@0
   101
	if (aStep!=ELastStep)
sl@0
   102
		{
sl@0
   103
		aStep=DoNextL(aStep);
sl@0
   104
		iState=ERunning;
sl@0
   105
		}
sl@0
   106
	else
sl@0
   107
		{
sl@0
   108
		DoLastL();
sl@0
   109
		aStep=0;
sl@0
   110
		iState=ECommitted;
sl@0
   111
		}
sl@0
   112
	return 0;	// return 0 for DDL incremental operations
sl@0
   113
	}
sl@0
   114
sl@0
   115
TInt CDbTableDatabase::CIncremental::DoNextL(TInt aStep)
sl@0
   116
//
sl@0
   117
// default use of stepper object (re-normalised the step count)
sl@0
   118
//
sl@0
   119
	{
sl@0
   120
	return iStepper->StepL(aStep-ELastStep)+ELastStep;
sl@0
   121
	}
sl@0
   122
sl@0
   123
// Class CDbTableDatabase::CIncrementalDDL
sl@0
   124
sl@0
   125
CDbTableDatabase::CIncrementalDDL::CIncrementalDDL(RDbTransaction& aTransaction)
sl@0
   126
	: CIncremental(aTransaction)
sl@0
   127
	{
sl@0
   128
	Transaction().DDLBegin();
sl@0
   129
	}
sl@0
   130
sl@0
   131
CDbTableDatabase::CIncrementalDDL::~CIncrementalDDL()
sl@0
   132
	{
sl@0
   133
	if (!IsCommitted())
sl@0
   134
		Transaction().DDLRollback();
sl@0
   135
	}
sl@0
   136
sl@0
   137
void CDbTableDatabase::CIncrementalDDL::DoLastL()
sl@0
   138
	{
sl@0
   139
	Transaction().DDLCommitL();
sl@0
   140
	}
sl@0
   141
sl@0
   142
// Class CDbTableDatabase::CBuildIndex
sl@0
   143
sl@0
   144
EXPORT_C CDbTableDatabase::CBuildIndex* CDbTableDatabase::CBuildIndex::NewL(CDbTableDatabase& aDatabase,const CDbTableDef& aTable,const CDbTableIndexDef& anIndex)
sl@0
   145
	{
sl@0
   146
	CBuildIndex* self=new(ELeave) CBuildIndex();
sl@0
   147
	CleanupStack::PushL(self);
sl@0
   148
	CDbTableSource* source=self->iSource=aDatabase.TableSourceL(aTable.Name());
sl@0
   149
	CDbTable& table=source->Table();
sl@0
   150
	source->SetIterator(table.IteratorL());
sl@0
   151
	self->iIndex=table.RecordIndexL(anIndex);
sl@0
   152
	self->iIndex->OpenL();
sl@0
   153
	CleanupStack::Pop();
sl@0
   154
	return self;
sl@0
   155
	}
sl@0
   156
sl@0
   157
CDbTableDatabase::CBuildIndex::CBuildIndex()
sl@0
   158
	: iNext(EDbFirst)
sl@0
   159
	{}
sl@0
   160
sl@0
   161
CDbTableDatabase::CBuildIndex::~CBuildIndex()
sl@0
   162
	{
sl@0
   163
	delete iIndex;
sl@0
   164
	delete iSource;
sl@0
   165
	}
sl@0
   166
sl@0
   167
EXPORT_C TInt CDbTableDatabase::CBuildIndex::Steps(TInt aCardinality)
sl@0
   168
	{
sl@0
   169
	return aCardinality+1;
sl@0
   170
	}
sl@0
   171
sl@0
   172
EXPORT_C TInt CDbTableDatabase::CBuildIndex::StepsL()
sl@0
   173
	{
sl@0
   174
	return Steps(iSource->CountL());
sl@0
   175
	}
sl@0
   176
sl@0
   177
TInt CDbTableDatabase::CBuildIndex::StepL(TInt aStep)
sl@0
   178
//
sl@0
   179
// One step on an incremental index build
sl@0
   180
//
sl@0
   181
	{
sl@0
   182
	for (TInt inc=1;;++inc)
sl@0
   183
		{
sl@0
   184
		TDbRecordId id;
sl@0
   185
		if (iSource->CDbDataSource::GotoL(iNext,id)!=CDbDataSource::ESuccess)
sl@0
   186
			break;	// run out of data
sl@0
   187
		iSource->ReadRowL(id);
sl@0
   188
		if (!iIndex->InsertL(id,iSource->Row()))
sl@0
   189
			__LEAVE(KErrAlreadyExists);		// duplicate key - fail
sl@0
   190
		iNext=EDbNext;
sl@0
   191
		if (inc==ERecordsPerStep)
sl@0
   192
			return Max(aStep-inc,1);
sl@0
   193
		}
sl@0
   194
	iIndex->FlushL();
sl@0
   195
	return 0;
sl@0
   196
	}
sl@0
   197
sl@0
   198
// Class CDbTableDatabase::CCreateIndex
sl@0
   199
sl@0
   200
CDbTableDatabase::CCreateIndex* CDbTableDatabase::CCreateIndex::NewLC(RDbTransaction& aTransaction)
sl@0
   201
	{
sl@0
   202
	CCreateIndex* self=new(ELeave) CCreateIndex(aTransaction);
sl@0
   203
	CleanupStack::PushL(self);
sl@0
   204
	return self;
sl@0
   205
	}
sl@0
   206
sl@0
   207
TInt CDbTableDatabase::CCreateIndex::ConstructL(const CDbTableDef& aTable,const CDbTableIndexDef& anIndex)
sl@0
   208
	{
sl@0
   209
	CBuildIndex* builder=CBuildIndex::NewL(Database(),aTable,anIndex);
sl@0
   210
	Construct(builder);
sl@0
   211
	return builder->StepsL();
sl@0
   212
	}
sl@0
   213
sl@0
   214
// Class CDbTableDatabase::CDropIndex
sl@0
   215
sl@0
   216
CDbTableDatabase::CDropIndex::~CDropIndex()
sl@0
   217
	{
sl@0
   218
	delete iDef;
sl@0
   219
	}
sl@0
   220
sl@0
   221
CDbTableDatabase::CDropIndex* CDbTableDatabase::CDropIndex::NewL(RDbTransaction& aTransaction,const CDbTableDef& aTable,CDbTableIndexDef* anIndex,TInt& aStep)
sl@0
   222
	{
sl@0
   223
	CDropIndex* self=new(ELeave) CDropIndex(aTransaction);
sl@0
   224
	CleanupStack::PushL(self);
sl@0
   225
	self->Construct(aTransaction.Database().IndexDiscarderL(aTable,*anIndex,aStep));
sl@0
   226
	self->iDef=anIndex;
sl@0
   227
	aStep+=ELastStep;
sl@0
   228
	CleanupStack::Pop();
sl@0
   229
	return self;
sl@0
   230
	}
sl@0
   231
sl@0
   232
// Class CDbTableDatabase::CDropTable
sl@0
   233
sl@0
   234
CDbTableDatabase::CDropTable::~CDropTable()
sl@0
   235
	{
sl@0
   236
	Database().Release(*iDef);		// discard the table using this definition
sl@0
   237
	delete iDef;
sl@0
   238
	}
sl@0
   239
sl@0
   240
CDbTableDatabase::CDropTable* CDbTableDatabase::CDropTable::NewL(RDbTransaction& aTransaction,CDbTableDef* aTable,TInt& aStep)
sl@0
   241
	{
sl@0
   242
	CDropTable* self=new(ELeave) CDropTable(aTransaction);
sl@0
   243
	CDbTableDatabase& database=aTransaction.Database();
sl@0
   244
	CleanupStack::PushL(self);
sl@0
   245
	CMultiStepper* mstepper=CMultiStepper::NewL(aTable->Indexes().Count()+1);
sl@0
   246
	self->Construct(mstepper);
sl@0
   247
	CStepper* stepper=database.RecordDiscarderL(*aTable,aStep);
sl@0
   248
	mstepper->AddStepper(stepper,aStep);
sl@0
   249
	TSglQueIterC<CDbTableIndexDef> iter(aTable->Indexes().AsQue());
sl@0
   250
	for (const CDbTableIndexDef* xDef;(xDef=iter++)!=0;)
sl@0
   251
		{
sl@0
   252
		stepper=database.IndexDiscarderL(*aTable,*xDef,aStep);
sl@0
   253
		mstepper->AddStepper(stepper,aStep);
sl@0
   254
		}
sl@0
   255
	aStep=mstepper->TotalSteps()+ELastStep;
sl@0
   256
	self->iDef=aTable;
sl@0
   257
	CleanupStack::Pop();
sl@0
   258
	return self;
sl@0
   259
	}
sl@0
   260
sl@0
   261
// Class CDbTableDatabase::CAlterTable
sl@0
   262
sl@0
   263
CDbTableDatabase::CAlterTable::~CAlterTable()
sl@0
   264
	{
sl@0
   265
	delete iNewSet;
sl@0
   266
	}
sl@0
   267
sl@0
   268
void CDbTableDatabase::CAlterTable::ConstructL(const CDbColSet& aNewDef,TInt& aStep)
sl@0
   269
//
sl@0
   270
// get all the deleted columns
sl@0
   271
// check changes to columns still present
sl@0
   272
// get all the new columns
sl@0
   273
// construct a new columns set based on the changes
sl@0
   274
//
sl@0
   275
	{
sl@0
   276
//
sl@0
   277
// flag all columns as dropped initially
sl@0
   278
	HDbColumnSet& columns=iDef.Columns();
sl@0
   279
	HDbColumnSet::TIterator iter=columns.Begin();
sl@0
   280
	HDbColumnSet::TIteratorC const end=columns.End();
sl@0
   281
	do
sl@0
   282
		{
sl@0
   283
		iter->iFlags=TDbColumnDef::EDropped;
sl@0
   284
		} while (++iter<end);
sl@0
   285
//
sl@0
   286
// look for additions and changes
sl@0
   287
	CDbColSet* change=CDbColSet::NewLC();
sl@0
   288
	CDbColSet* add=CDbColSet::NewLC();
sl@0
   289
	for (TDbColSetIter iterNew(aNewDef);iterNew;++iterNew)
sl@0
   290
		{
sl@0
   291
		const TDbCol& col=*iterNew;
sl@0
   292
		TDbColumnDef* def=columns.ColumnL(iterNew->iName);
sl@0
   293
		if (!def)	// a new column
sl@0
   294
			add->AddL(col);
sl@0
   295
		else
sl@0
   296
			{	// see if the definition has changed
sl@0
   297
			if (def->iAttributes!=col.iAttributes)
sl@0
   298
				__LEAVE(KErrArgument);		// can't change attributes
sl@0
   299
			TUint8 flag=0;
sl@0
   300
			if (def->iType!=col.iType)
sl@0
   301
				flag=TDbColumnDef::EChangedType;
sl@0
   302
			else if (def->iType>=EDbColText8 && col.iMaxLength!=KDbUndefinedLength && col.iMaxLength!=def->iMaxLength)
sl@0
   303
				flag=TDbColumnDef::EChangedLen;
sl@0
   304
			def->iFlags=flag;
sl@0
   305
			if (flag)
sl@0
   306
				change->AddL(col);	// column has changed
sl@0
   307
			}
sl@0
   308
		}
sl@0
   309
//
sl@0
   310
// check that all marked columns are not indexed
sl@0
   311
//
sl@0
   312
	iter=columns.Begin();
sl@0
   313
	do
sl@0
   314
		{
sl@0
   315
		if (iter->iFlags && iDef.IsIndexed(*iter->iName))
sl@0
   316
			__LEAVE(KErrArgument);		// can't remove indexed column
sl@0
   317
		} while (++iter<end);
sl@0
   318
//
sl@0
   319
	iNewSet=HDbColumnSet::NewL(aNewDef.Count());
sl@0
   320
	iDef.AlteredColumnSetL(*iNewSet,*change,*add);
sl@0
   321
	CleanupStack::PopAndDestroy(2);	// add, change
sl@0
   322
	Construct(Database().TableAlterL(iDef,*iNewSet,aStep));
sl@0
   323
	}
sl@0
   324
sl@0
   325
CDbTableDatabase::CAlterTable* CDbTableDatabase::CAlterTable::NewL(RDbTransaction& aTransaction,CDbTableDef& aTable,const CDbColSet& aNewDef,TInt& aStep)
sl@0
   326
//
sl@0
   327
// Check the validity of the new definition before asking the implentation to provide
sl@0
   328
// the incremental class
sl@0
   329
//
sl@0
   330
	{
sl@0
   331
	CAlterTable* self=new(ELeave) CAlterTable(aTransaction,aTable);
sl@0
   332
	CleanupStack::PushL(self);
sl@0
   333
	self->ConstructL(aNewDef,aStep);
sl@0
   334
	aStep+=ELastStep;
sl@0
   335
	CleanupStack::Pop();
sl@0
   336
	return self;
sl@0
   337
	}
sl@0
   338
sl@0
   339
void CDbTableDatabase::CAlterTable::DoLastL()
sl@0
   340
//
sl@0
   341
// last step is to change the definition
sl@0
   342
//
sl@0
   343
	{
sl@0
   344
	iDef.ExchangeColumnSet(iNewSet);
sl@0
   345
	iNewSet=0;
sl@0
   346
	CIncrementalDDL::DoLastL();
sl@0
   347
	}
sl@0
   348
sl@0
   349
// Class CDbTableDatabase::CUtility
sl@0
   350
sl@0
   351
inline CDbTableDatabase::CUtility::CUtility(RDbTransaction& aTransaction,CDbDatabase::TUtility aType)
sl@0
   352
	: CIncremental(aTransaction)
sl@0
   353
	{Transaction().UtilityBegin(aType);}
sl@0
   354
sl@0
   355
CDbTableDatabase::CUtility::~CUtility()
sl@0
   356
	{
sl@0
   357
	if (!IsCommitted())
sl@0
   358
		Transaction().UtilityRollback();
sl@0
   359
	}
sl@0
   360
sl@0
   361
CDbTableDatabase::CUtility* CDbTableDatabase::CUtility::NewL(RDbTransaction& aTransaction,CDbDatabase::TUtility aType,TInt& aStep)
sl@0
   362
	{
sl@0
   363
	CUtility* self=new(ELeave) CUtility(aTransaction,aType);
sl@0
   364
	CleanupStack::PushL(self);
sl@0
   365
	self->Construct(aTransaction.Database().UtilityL(aType,aStep));
sl@0
   366
	aStep+=ELastStep;
sl@0
   367
	CleanupStack::Pop();
sl@0
   368
	return self;
sl@0
   369
	}
sl@0
   370
sl@0
   371
void CDbTableDatabase::CUtility::DoLastL()
sl@0
   372
	{
sl@0
   373
	Transaction().UtilityCommitL();
sl@0
   374
	}