1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/dbms/pcdbms/utable/UT_INCR.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,374 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "UT_STD.H"
1.20 +#include "U32STD_DBMS.H"
1.21 +// Class CDbTableDatabase::CMultiStepper
1.22 +
1.23 +inline CDbTableDatabase::CMultiStepper::CMultiStepper( TInt aCount )
1.24 + : iStepper( iSteppers - 1 ), iEnd( iSteppers + aCount )
1.25 + {}
1.26 +
1.27 +CDbTableDatabase::CMultiStepper::~CMultiStepper()
1.28 + {
1.29 + SStepper* const end = iEnd;
1.30 + for ( SStepper* iter = iSteppers; iter < end; ++iter )
1.31 + delete iter->iStepper;
1.32 + }
1.33 +
1.34 +EXPORT_C CDbTableDatabase::CMultiStepper* CDbTableDatabase::CMultiStepper::NewL( TInt aStepperCount )
1.35 + {
1.36 + return new( ELeave, sizeof( SStepper ) * ( aStepperCount - 1 ) ) CMultiStepper( aStepperCount ); // get the extra size for the entries, leaves on error
1.37 + }
1.38 +
1.39 +EXPORT_C void CDbTableDatabase::CMultiStepper::AddStepper( CStepper* aStepper, TInt aStep )
1.40 + {
1.41 + ++iStepper;
1.42 + __ASSERT( iStepper < iEnd );
1.43 + iStepper->iStepper = aStepper;
1.44 + iStepper->iStep = aStep;
1.45 + }
1.46 +
1.47 +EXPORT_C TInt CDbTableDatabase::CMultiStepper::TotalSteps()
1.48 +//
1.49 +// Count the number of steps, and normalise the step counts
1.50 +//
1.51 + {
1.52 + TInt steps = 0;
1.53 + SStepper* const end = iStepper;
1.54 + for( SStepper* stepper = iSteppers; stepper <= end; ++stepper )
1.55 + {
1.56 + TInt step = stepper->iStep;
1.57 + stepper->iStep = steps;
1.58 + steps += step;
1.59 + }
1.60 + return steps;
1.61 + }
1.62 +
1.63 +TInt CDbTableDatabase::CMultiStepper::StepL( TInt aStep )
1.64 + {
1.65 + SStepper* stepper = iStepper;
1.66 + __ASSERT( stepper != 0 && stepper >= iSteppers );
1.67 + TInt base;
1.68 + for ( ; ; )
1.69 + {
1.70 + base = stepper->iStep;
1.71 + if ( aStep > base )
1.72 + break;
1.73 + if ( --stepper < iSteppers )
1.74 + return 0;
1.75 + iStepper = stepper;
1.76 + }
1.77 + return stepper->iStepper->StepL( aStep - base ) + base;
1.78 + }
1.79 +
1.80 +// Class CDbTableDatabase::CIncremental
1.81 +
1.82 +CDbTableDatabase::CIncremental::CIncremental(RDbTransaction& aTransaction)
1.83 + : iTransaction(aTransaction)
1.84 + {
1.85 + Database().Open(); // we reference the database
1.86 + __ASSERT(iState==ERunning);
1.87 + }
1.88 +
1.89 +CDbTableDatabase::CIncremental::~CIncremental()
1.90 + {
1.91 + delete iStepper;
1.92 + Database().Close(); // drop the database reference
1.93 + }
1.94 +
1.95 +TBool CDbTableDatabase::CIncremental::NextL(TInt& aStep)
1.96 +//
1.97 +// if step is 1 then invopke the last step otherwise do
1.98 +//
1.99 + {
1.100 + __ASSERT(!IsCommitted());
1.101 + if (iState==EFailed)
1.102 + __LEAVE(KErrDied);
1.103 + iState=EFailed;
1.104 + if (aStep!=ELastStep)
1.105 + {
1.106 + aStep=DoNextL(aStep);
1.107 + iState=ERunning;
1.108 + }
1.109 + else
1.110 + {
1.111 + DoLastL();
1.112 + aStep=0;
1.113 + iState=ECommitted;
1.114 + }
1.115 + return 0; // return 0 for DDL incremental operations
1.116 + }
1.117 +
1.118 +TInt CDbTableDatabase::CIncremental::DoNextL(TInt aStep)
1.119 +//
1.120 +// default use of stepper object (re-normalised the step count)
1.121 +//
1.122 + {
1.123 + return iStepper->StepL(aStep-ELastStep)+ELastStep;
1.124 + }
1.125 +
1.126 +// Class CDbTableDatabase::CIncrementalDDL
1.127 +
1.128 +CDbTableDatabase::CIncrementalDDL::CIncrementalDDL(RDbTransaction& aTransaction)
1.129 + : CIncremental(aTransaction)
1.130 + {
1.131 + Transaction().DDLBegin();
1.132 + }
1.133 +
1.134 +CDbTableDatabase::CIncrementalDDL::~CIncrementalDDL()
1.135 + {
1.136 + if (!IsCommitted())
1.137 + Transaction().DDLRollback();
1.138 + }
1.139 +
1.140 +void CDbTableDatabase::CIncrementalDDL::DoLastL()
1.141 + {
1.142 + Transaction().DDLCommitL();
1.143 + }
1.144 +
1.145 +// Class CDbTableDatabase::CBuildIndex
1.146 +
1.147 +EXPORT_C CDbTableDatabase::CBuildIndex* CDbTableDatabase::CBuildIndex::NewL(CDbTableDatabase& aDatabase,const CDbTableDef& aTable,const CDbTableIndexDef& anIndex)
1.148 + {
1.149 + CBuildIndex* self=new(ELeave) CBuildIndex();
1.150 + CleanupStack::PushL(self);
1.151 + CDbTableSource* source=self->iSource=aDatabase.TableSourceL(aTable.Name());
1.152 + CDbTable& table=source->Table();
1.153 + source->SetIterator(table.IteratorL());
1.154 + self->iIndex=table.RecordIndexL(anIndex);
1.155 + self->iIndex->OpenL();
1.156 + CleanupStack::Pop();
1.157 + return self;
1.158 + }
1.159 +
1.160 +CDbTableDatabase::CBuildIndex::CBuildIndex()
1.161 + : iNext(EDbFirst)
1.162 + {}
1.163 +
1.164 +CDbTableDatabase::CBuildIndex::~CBuildIndex()
1.165 + {
1.166 + delete iIndex;
1.167 + delete iSource;
1.168 + }
1.169 +
1.170 +EXPORT_C TInt CDbTableDatabase::CBuildIndex::Steps(TInt aCardinality)
1.171 + {
1.172 + return aCardinality+1;
1.173 + }
1.174 +
1.175 +EXPORT_C TInt CDbTableDatabase::CBuildIndex::StepsL()
1.176 + {
1.177 + return Steps(iSource->CountL());
1.178 + }
1.179 +
1.180 +TInt CDbTableDatabase::CBuildIndex::StepL(TInt aStep)
1.181 +//
1.182 +// One step on an incremental index build
1.183 +//
1.184 + {
1.185 + for (TInt inc=1;;++inc)
1.186 + {
1.187 + TDbRecordId id;
1.188 + if (iSource->CDbDataSource::GotoL(iNext,id)!=CDbDataSource::ESuccess)
1.189 + break; // run out of data
1.190 + iSource->ReadRowL(id);
1.191 + if (!iIndex->InsertL(id,iSource->Row()))
1.192 + __LEAVE(KErrAlreadyExists); // duplicate key - fail
1.193 + iNext=EDbNext;
1.194 + if (inc==ERecordsPerStep)
1.195 + return Max(aStep-inc,1);
1.196 + }
1.197 + iIndex->FlushL();
1.198 + return 0;
1.199 + }
1.200 +
1.201 +// Class CDbTableDatabase::CCreateIndex
1.202 +
1.203 +CDbTableDatabase::CCreateIndex* CDbTableDatabase::CCreateIndex::NewLC(RDbTransaction& aTransaction)
1.204 + {
1.205 + CCreateIndex* self=new(ELeave) CCreateIndex(aTransaction);
1.206 + CleanupStack::PushL(self);
1.207 + return self;
1.208 + }
1.209 +
1.210 +TInt CDbTableDatabase::CCreateIndex::ConstructL(const CDbTableDef& aTable,const CDbTableIndexDef& anIndex)
1.211 + {
1.212 + CBuildIndex* builder=CBuildIndex::NewL(Database(),aTable,anIndex);
1.213 + Construct(builder);
1.214 + return builder->StepsL();
1.215 + }
1.216 +
1.217 +// Class CDbTableDatabase::CDropIndex
1.218 +
1.219 +CDbTableDatabase::CDropIndex::~CDropIndex()
1.220 + {
1.221 + delete iDef;
1.222 + }
1.223 +
1.224 +CDbTableDatabase::CDropIndex* CDbTableDatabase::CDropIndex::NewL(RDbTransaction& aTransaction,const CDbTableDef& aTable,CDbTableIndexDef* anIndex,TInt& aStep)
1.225 + {
1.226 + CDropIndex* self=new(ELeave) CDropIndex(aTransaction);
1.227 + CleanupStack::PushL(self);
1.228 + self->Construct(aTransaction.Database().IndexDiscarderL(aTable,*anIndex,aStep));
1.229 + self->iDef=anIndex;
1.230 + aStep+=ELastStep;
1.231 + CleanupStack::Pop();
1.232 + return self;
1.233 + }
1.234 +
1.235 +// Class CDbTableDatabase::CDropTable
1.236 +
1.237 +CDbTableDatabase::CDropTable::~CDropTable()
1.238 + {
1.239 + Database().Release(*iDef); // discard the table using this definition
1.240 + delete iDef;
1.241 + }
1.242 +
1.243 +CDbTableDatabase::CDropTable* CDbTableDatabase::CDropTable::NewL(RDbTransaction& aTransaction,CDbTableDef* aTable,TInt& aStep)
1.244 + {
1.245 + CDropTable* self=new(ELeave) CDropTable(aTransaction);
1.246 + CDbTableDatabase& database=aTransaction.Database();
1.247 + CleanupStack::PushL(self);
1.248 + CMultiStepper* mstepper=CMultiStepper::NewL(aTable->Indexes().Count()+1);
1.249 + self->Construct(mstepper);
1.250 + CStepper* stepper=database.RecordDiscarderL(*aTable,aStep);
1.251 + mstepper->AddStepper(stepper,aStep);
1.252 + TSglQueIterC<CDbTableIndexDef> iter(aTable->Indexes().AsQue());
1.253 + for (const CDbTableIndexDef* xDef;(xDef=iter++)!=0;)
1.254 + {
1.255 + stepper=database.IndexDiscarderL(*aTable,*xDef,aStep);
1.256 + mstepper->AddStepper(stepper,aStep);
1.257 + }
1.258 + aStep=mstepper->TotalSteps()+ELastStep;
1.259 + self->iDef=aTable;
1.260 + CleanupStack::Pop();
1.261 + return self;
1.262 + }
1.263 +
1.264 +// Class CDbTableDatabase::CAlterTable
1.265 +
1.266 +CDbTableDatabase::CAlterTable::~CAlterTable()
1.267 + {
1.268 + delete iNewSet;
1.269 + }
1.270 +
1.271 +void CDbTableDatabase::CAlterTable::ConstructL(const CDbColSet& aNewDef,TInt& aStep)
1.272 +//
1.273 +// get all the deleted columns
1.274 +// check changes to columns still present
1.275 +// get all the new columns
1.276 +// construct a new columns set based on the changes
1.277 +//
1.278 + {
1.279 +//
1.280 +// flag all columns as dropped initially
1.281 + HDbColumnSet& columns=iDef.Columns();
1.282 + HDbColumnSet::TIterator iter=columns.Begin();
1.283 + HDbColumnSet::TIteratorC const end=columns.End();
1.284 + do
1.285 + {
1.286 + iter->iFlags=TDbColumnDef::EDropped;
1.287 + } while (++iter<end);
1.288 +//
1.289 +// look for additions and changes
1.290 + CDbColSet* change=CDbColSet::NewLC();
1.291 + CDbColSet* add=CDbColSet::NewLC();
1.292 + for (TDbColSetIter iterNew(aNewDef);iterNew;++iterNew)
1.293 + {
1.294 + const TDbCol& col=*iterNew;
1.295 + TDbColumnDef* def=columns.ColumnL(iterNew->iName);
1.296 + if (!def) // a new column
1.297 + add->AddL(col);
1.298 + else
1.299 + { // see if the definition has changed
1.300 + if (def->iAttributes!=col.iAttributes)
1.301 + __LEAVE(KErrArgument); // can't change attributes
1.302 + TUint8 flag=0;
1.303 + if (def->iType!=col.iType)
1.304 + flag=TDbColumnDef::EChangedType;
1.305 + else if (def->iType>=EDbColText8 && col.iMaxLength!=KDbUndefinedLength && col.iMaxLength!=def->iMaxLength)
1.306 + flag=TDbColumnDef::EChangedLen;
1.307 + def->iFlags=flag;
1.308 + if (flag)
1.309 + change->AddL(col); // column has changed
1.310 + }
1.311 + }
1.312 +//
1.313 +// check that all marked columns are not indexed
1.314 +//
1.315 + iter=columns.Begin();
1.316 + do
1.317 + {
1.318 + if (iter->iFlags && iDef.IsIndexed(*iter->iName))
1.319 + __LEAVE(KErrArgument); // can't remove indexed column
1.320 + } while (++iter<end);
1.321 +//
1.322 + iNewSet=HDbColumnSet::NewL(aNewDef.Count());
1.323 + iDef.AlteredColumnSetL(*iNewSet,*change,*add);
1.324 + CleanupStack::PopAndDestroy(2); // add, change
1.325 + Construct(Database().TableAlterL(iDef,*iNewSet,aStep));
1.326 + }
1.327 +
1.328 +CDbTableDatabase::CAlterTable* CDbTableDatabase::CAlterTable::NewL(RDbTransaction& aTransaction,CDbTableDef& aTable,const CDbColSet& aNewDef,TInt& aStep)
1.329 +//
1.330 +// Check the validity of the new definition before asking the implentation to provide
1.331 +// the incremental class
1.332 +//
1.333 + {
1.334 + CAlterTable* self=new(ELeave) CAlterTable(aTransaction,aTable);
1.335 + CleanupStack::PushL(self);
1.336 + self->ConstructL(aNewDef,aStep);
1.337 + aStep+=ELastStep;
1.338 + CleanupStack::Pop();
1.339 + return self;
1.340 + }
1.341 +
1.342 +void CDbTableDatabase::CAlterTable::DoLastL()
1.343 +//
1.344 +// last step is to change the definition
1.345 +//
1.346 + {
1.347 + iDef.ExchangeColumnSet(iNewSet);
1.348 + iNewSet=0;
1.349 + CIncrementalDDL::DoLastL();
1.350 + }
1.351 +
1.352 +// Class CDbTableDatabase::CUtility
1.353 +
1.354 +inline CDbTableDatabase::CUtility::CUtility(RDbTransaction& aTransaction,CDbDatabase::TUtility aType)
1.355 + : CIncremental(aTransaction)
1.356 + {Transaction().UtilityBegin(aType);}
1.357 +
1.358 +CDbTableDatabase::CUtility::~CUtility()
1.359 + {
1.360 + if (!IsCommitted())
1.361 + Transaction().UtilityRollback();
1.362 + }
1.363 +
1.364 +CDbTableDatabase::CUtility* CDbTableDatabase::CUtility::NewL(RDbTransaction& aTransaction,CDbDatabase::TUtility aType,TInt& aStep)
1.365 + {
1.366 + CUtility* self=new(ELeave) CUtility(aTransaction,aType);
1.367 + CleanupStack::PushL(self);
1.368 + self->Construct(aTransaction.Database().UtilityL(aType,aStep));
1.369 + aStep+=ELastStep;
1.370 + CleanupStack::Pop();
1.371 + return self;
1.372 + }
1.373 +
1.374 +void CDbTableDatabase::CUtility::DoLastL()
1.375 + {
1.376 + Transaction().UtilityCommitL();
1.377 + }