persistentstorage/dbms/pcdbms/utable/UT_INCR.CPP
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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 #include "U32STD_DBMS.H"
       
    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 	}