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