diff -r 000000000000 -r 08ec8eefde2f persistentstorage/dbms/utable/UT_INCR.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/dbms/utable/UT_INCR.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,374 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "UT_STD.H" + +// Class CDbTableDatabase::CMultiStepper + +inline CDbTableDatabase::CMultiStepper::CMultiStepper( TInt aCount ) + : iStepper( iSteppers - 1 ), iEnd( iSteppers + aCount ) + {} + +CDbTableDatabase::CMultiStepper::~CMultiStepper() + { + SStepper* const end = iEnd; + for ( SStepper* iter = iSteppers; iter < end; ++iter ) + delete iter->iStepper; + } + +EXPORT_C CDbTableDatabase::CMultiStepper* CDbTableDatabase::CMultiStepper::NewL( TInt aStepperCount ) + { + return new( ELeave, sizeof( SStepper ) * ( aStepperCount - 1 ) ) CMultiStepper( aStepperCount ); // get the extra size for the entries, leaves on error + } + +EXPORT_C void CDbTableDatabase::CMultiStepper::AddStepper( CStepper* aStepper, TInt aStep ) + { + ++iStepper; + __ASSERT( iStepper < iEnd ); + iStepper->iStepper = aStepper; + iStepper->iStep = aStep; + } + +EXPORT_C TInt CDbTableDatabase::CMultiStepper::TotalSteps() +// +// Count the number of steps, and normalise the step counts +// + { + TInt steps = 0; + SStepper* const end = iStepper; + for( SStepper* stepper = iSteppers; stepper <= end; ++stepper ) + { + TInt step = stepper->iStep; + stepper->iStep = steps; + steps += step; + } + return steps; + } + +TInt CDbTableDatabase::CMultiStepper::StepL( TInt aStep ) + { + SStepper* stepper = iStepper; + __ASSERT( stepper != 0 && stepper >= iSteppers ); + TInt base; + for ( ; ; ) + { + base = stepper->iStep; + if ( aStep > base ) + break; + if ( --stepper < iSteppers ) + return 0; + iStepper = stepper; + } + return stepper->iStepper->StepL( aStep - base ) + base; + } + +// Class CDbTableDatabase::CIncremental + +CDbTableDatabase::CIncremental::CIncremental(RDbTransaction& aTransaction) + : iTransaction(aTransaction) + { + Database().Open(); // we reference the database + __ASSERT(iState==ERunning); + } + +CDbTableDatabase::CIncremental::~CIncremental() + { + delete iStepper; + Database().Close(); // drop the database reference + } + +TBool CDbTableDatabase::CIncremental::NextL(TInt& aStep) +// +// if step is 1 then invopke the last step otherwise do +// + { + __ASSERT(!IsCommitted()); + if (iState==EFailed) + __LEAVE(KErrDied); + iState=EFailed; + if (aStep!=ELastStep) + { + aStep=DoNextL(aStep); + iState=ERunning; + } + else + { + DoLastL(); + aStep=0; + iState=ECommitted; + } + return 0; // return 0 for DDL incremental operations + } + +TInt CDbTableDatabase::CIncremental::DoNextL(TInt aStep) +// +// default use of stepper object (re-normalised the step count) +// + { + return iStepper->StepL(aStep-ELastStep)+ELastStep; + } + +// Class CDbTableDatabase::CIncrementalDDL + +CDbTableDatabase::CIncrementalDDL::CIncrementalDDL(RDbTransaction& aTransaction) + : CIncremental(aTransaction) + { + Transaction().DDLBegin(); + } + +CDbTableDatabase::CIncrementalDDL::~CIncrementalDDL() + { + if (!IsCommitted()) + Transaction().DDLRollback(); + } + +void CDbTableDatabase::CIncrementalDDL::DoLastL() + { + Transaction().DDLCommitL(); + } + +// Class CDbTableDatabase::CBuildIndex + +EXPORT_C CDbTableDatabase::CBuildIndex* CDbTableDatabase::CBuildIndex::NewL(CDbTableDatabase& aDatabase,const CDbTableDef& aTable,const CDbTableIndexDef& anIndex) + { + CBuildIndex* self=new(ELeave) CBuildIndex(); + CleanupStack::PushL(self); + CDbTableSource* source=self->iSource=aDatabase.TableSourceL(aTable.Name()); + CDbTable& table=source->Table(); + source->SetIterator(table.IteratorL()); + self->iIndex=table.RecordIndexL(anIndex); + self->iIndex->OpenL(); + CleanupStack::Pop(); + return self; + } + +CDbTableDatabase::CBuildIndex::CBuildIndex() + : iNext(EDbFirst) + {} + +CDbTableDatabase::CBuildIndex::~CBuildIndex() + { + delete iIndex; + delete iSource; + } + +EXPORT_C TInt CDbTableDatabase::CBuildIndex::Steps(TInt aCardinality) + { + return aCardinality+1; + } + +EXPORT_C TInt CDbTableDatabase::CBuildIndex::StepsL() + { + return Steps(iSource->CountL()); + } + +TInt CDbTableDatabase::CBuildIndex::StepL(TInt aStep) +// +// One step on an incremental index build +// + { + for (TInt inc=1;;++inc) + { + TDbRecordId id; + if (iSource->CDbDataSource::GotoL(iNext,id)!=CDbDataSource::ESuccess) + break; // run out of data + iSource->ReadRowL(id); + if (!iIndex->InsertL(id,iSource->Row())) + __LEAVE(KErrAlreadyExists); // duplicate key - fail + iNext=EDbNext; + if (inc==ERecordsPerStep) + return Max(aStep-inc,1); + } + iIndex->FlushL(); + return 0; + } + +// Class CDbTableDatabase::CCreateIndex + +CDbTableDatabase::CCreateIndex* CDbTableDatabase::CCreateIndex::NewLC(RDbTransaction& aTransaction) + { + CCreateIndex* self=new(ELeave) CCreateIndex(aTransaction); + CleanupStack::PushL(self); + return self; + } + +TInt CDbTableDatabase::CCreateIndex::ConstructL(const CDbTableDef& aTable,const CDbTableIndexDef& anIndex) + { + CBuildIndex* builder=CBuildIndex::NewL(Database(),aTable,anIndex); + Construct(builder); + return builder->StepsL(); + } + +// Class CDbTableDatabase::CDropIndex + +CDbTableDatabase::CDropIndex::~CDropIndex() + { + delete iDef; + } + +CDbTableDatabase::CDropIndex* CDbTableDatabase::CDropIndex::NewL(RDbTransaction& aTransaction,const CDbTableDef& aTable,CDbTableIndexDef* anIndex,TInt& aStep) + { + CDropIndex* self=new(ELeave) CDropIndex(aTransaction); + CleanupStack::PushL(self); + self->Construct(aTransaction.Database().IndexDiscarderL(aTable,*anIndex,aStep)); + self->iDef=anIndex; + aStep+=ELastStep; + CleanupStack::Pop(); + return self; + } + +// Class CDbTableDatabase::CDropTable + +CDbTableDatabase::CDropTable::~CDropTable() + { + Database().Release(*iDef); // discard the table using this definition + delete iDef; + } + +CDbTableDatabase::CDropTable* CDbTableDatabase::CDropTable::NewL(RDbTransaction& aTransaction,CDbTableDef* aTable,TInt& aStep) + { + CDropTable* self=new(ELeave) CDropTable(aTransaction); + CDbTableDatabase& database=aTransaction.Database(); + CleanupStack::PushL(self); + CMultiStepper* mstepper=CMultiStepper::NewL(aTable->Indexes().Count()+1); + self->Construct(mstepper); + CStepper* stepper=database.RecordDiscarderL(*aTable,aStep); + mstepper->AddStepper(stepper,aStep); + TSglQueIterC iter(aTable->Indexes().AsQue()); + for (const CDbTableIndexDef* xDef;(xDef=iter++)!=0;) + { + stepper=database.IndexDiscarderL(*aTable,*xDef,aStep); + mstepper->AddStepper(stepper,aStep); + } + aStep=mstepper->TotalSteps()+ELastStep; + self->iDef=aTable; + CleanupStack::Pop(); + return self; + } + +// Class CDbTableDatabase::CAlterTable + +CDbTableDatabase::CAlterTable::~CAlterTable() + { + delete iNewSet; + } + +void CDbTableDatabase::CAlterTable::ConstructL(const CDbColSet& aNewDef,TInt& aStep) +// +// get all the deleted columns +// check changes to columns still present +// get all the new columns +// construct a new columns set based on the changes +// + { +// +// flag all columns as dropped initially + HDbColumnSet& columns=iDef.Columns(); + HDbColumnSet::TIterator iter=columns.Begin(); + HDbColumnSet::TIteratorC const end=columns.End(); + do + { + iter->iFlags=TDbColumnDef::EDropped; + } while (++iteriName); + if (!def) // a new column + add->AddL(col); + else + { // see if the definition has changed + if (def->iAttributes!=col.iAttributes) + __LEAVE(KErrArgument); // can't change attributes + TUint8 flag=0; + if (def->iType!=col.iType) + flag=TDbColumnDef::EChangedType; + else if (def->iType>=EDbColText8 && col.iMaxLength!=KDbUndefinedLength && col.iMaxLength!=def->iMaxLength) + flag=TDbColumnDef::EChangedLen; + def->iFlags=flag; + if (flag) + change->AddL(col); // column has changed + } + } +// +// check that all marked columns are not indexed +// + iter=columns.Begin(); + do + { + if (iter->iFlags && iDef.IsIndexed(*iter->iName)) + __LEAVE(KErrArgument); // can't remove indexed column + } while (++iterConstructL(aNewDef,aStep); + aStep+=ELastStep; + CleanupStack::Pop(); + return self; + } + +void CDbTableDatabase::CAlterTable::DoLastL() +// +// last step is to change the definition +// + { + iDef.ExchangeColumnSet(iNewSet); + iNewSet=0; + CIncrementalDDL::DoLastL(); + } + +// Class CDbTableDatabase::CUtility + +inline CDbTableDatabase::CUtility::CUtility(RDbTransaction& aTransaction,CDbDatabase::TUtility aType) + : CIncremental(aTransaction) + {Transaction().UtilityBegin(aType);} + +CDbTableDatabase::CUtility::~CUtility() + { + if (!IsCommitted()) + Transaction().UtilityRollback(); + } + +CDbTableDatabase::CUtility* CDbTableDatabase::CUtility::NewL(RDbTransaction& aTransaction,CDbDatabase::TUtility aType,TInt& aStep) + { + CUtility* self=new(ELeave) CUtility(aTransaction,aType); + CleanupStack::PushL(self); + self->Construct(aTransaction.Database().UtilityL(aType,aStep)); + aStep+=ELastStep; + CleanupStack::Pop(); + return self; + } + +void CDbTableDatabase::CUtility::DoLastL() + { + Transaction().UtilityCommitL(); + }