os/persistentdata/persistentstorage/dbms/pcdbms/utable/UT_INCR.CPP
changeset 0 bde4ae8d615e
     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 +	}