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