persistentstorage/dbms/utable/UT_DBS.CPP
changeset 0 08ec8eefde2f
child 55 44f437012c90
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 
       
    18 // Class CDbTableDatabase::CInterface
       
    19 
       
    20 //
       
    21 // ctor. Add the initial reference to the database engine
       
    22 //
       
    23 CDbTableDatabase::CInterface::CInterface(CDbTableDatabase& aDatabase)
       
    24 	:iDatabase(aDatabase)
       
    25 	{
       
    26 	aDatabase.Open();
       
    27 	}
       
    28 
       
    29 //
       
    30 // dtor. remove our reference from the database engine
       
    31 //
       
    32 CDbTableDatabase::CInterface::~CInterface()
       
    33 	{
       
    34 	if (Database().Transaction().InTransaction(*this))
       
    35 		Rollback();			// release the lock if we have it
       
    36 	Database().Close();
       
    37 	}
       
    38 
       
    39 void CDbTableDatabase::CInterface::PrepareDDLL()
       
    40 	{
       
    41 	Database().Transaction().DDLPrepareL(*this);
       
    42 	}
       
    43 
       
    44 //
       
    45 // destroy the database (database must be empty)
       
    46 //
       
    47 TInt CDbTableDatabase::CInterface::Destroy()
       
    48 	{
       
    49 	__ASSERT(Database().Schema().IsEmpty());
       
    50 	TRAPD(r,Database().DestroyL());
       
    51 	return r;
       
    52 	}
       
    53 
       
    54 //
       
    55 // Initiate a transaction on the database
       
    56 //
       
    57 TInt CDbTableDatabase::CInterface::Begin()
       
    58 	{
       
    59 	TRAPD(r,Database().Transaction().BeginL(*this));
       
    60 	return r;
       
    61 	}
       
    62 
       
    63 //
       
    64 // Commit a transaction on the database
       
    65 //
       
    66 TInt CDbTableDatabase::CInterface::Commit()
       
    67 	{
       
    68 	TRAPD(r,Database().Transaction().CommitL(*this));
       
    69 	return r;
       
    70 	}
       
    71 
       
    72 //
       
    73 // Rollback a failed transaction on the database
       
    74 //
       
    75 void CDbTableDatabase::CInterface::Rollback()
       
    76 	{
       
    77 	Database().Transaction().Rollback(*this);
       
    78 	}
       
    79 
       
    80 //
       
    81 // Report a requested property
       
    82 //
       
    83 TInt CDbTableDatabase::CInterface::Property(CDbDatabase::TProperty aProperty)
       
    84 	{
       
    85 	if (aProperty==EInTransaction)
       
    86 		return Database().Transaction().InTransaction(*this) ? 1 : 0;
       
    87 //
       
    88 	return Database().Property(aProperty);
       
    89 	}
       
    90 
       
    91 void CDbTableDatabase::CInterface::CreateTableL(const TDesC& aName,const CDbColSet& aColSet,const CDbKey* aPrimaryKey)
       
    92 	{
       
    93 	PrepareDDLL();
       
    94 	Database().DoCreateTableL(aName,aColSet,aPrimaryKey);
       
    95 	}
       
    96 
       
    97 CDbCursor* CDbTableDatabase::CInterface::PrepareViewL(const TDbQuery& aQuery,const TDbWindow& aWindow,RDbRowSet::TAccess anAccess)
       
    98 	{
       
    99 	return Database().PrepareViewL(aQuery,aWindow,anAccess);
       
   100 	}
       
   101 
       
   102 CDbCursor* CDbTableDatabase::CInterface::OpenTableL(const TDesC& aName,RDbRowSet::TAccess anAccess)
       
   103 	{
       
   104 	return Database().PrepareTableL(aName,anAccess);
       
   105 	}
       
   106 
       
   107 CDbIncremental* CDbTableDatabase::CInterface::OpenDropTableL(const TDesC& aTable,TInt& aStep)
       
   108 	{
       
   109 	PrepareDDLL();
       
   110 	return Database().OpenDropTableL(aTable,aStep);
       
   111 	}
       
   112 
       
   113 CDbIncremental* CDbTableDatabase::CInterface::OpenAlterTableL(const TDesC& aTable,const CDbColSet& aNewDef,TInt& aStep)
       
   114 	{
       
   115 	PrepareDDLL();
       
   116 	return Database().OpenAlterTableL(aTable,aNewDef,aStep);
       
   117 	}
       
   118 
       
   119 CDbIncremental* CDbTableDatabase::CInterface::OpenCreateIndexL(const TDesC& aName,const TDesC& aTable,const CDbKey& aKey,TInt& aStep)
       
   120 	{
       
   121 	PrepareDDLL();
       
   122 	return Database().OpenCreateIndexL(aName,aTable,aKey,aStep);
       
   123 	}
       
   124 
       
   125 CDbIncremental* CDbTableDatabase::CInterface::OpenDropIndexL(const TDesC& aName,const TDesC& aTable,TInt& aStep)
       
   126 	{
       
   127 	PrepareDDLL();
       
   128 	return Database().OpenDropIndexL(aName,aTable,aStep);
       
   129 	}
       
   130 
       
   131 //
       
   132 // Create a database utility. Check the corresponding property to see if it is viable
       
   133 //
       
   134 CDbIncremental* CDbTableDatabase::CInterface::OpenUtilityL(CDbDatabase::TUtility aType,TInt& aStep)
       
   135 	{
       
   136 	if (!Property(TProperty(-aType)))
       
   137 		{	// nothing to do, or not capable
       
   138 		aStep=0;
       
   139 		return 0;
       
   140 		}
       
   141 	RDbTransaction& t=Database().Transaction();
       
   142 	t.UtilityPrepareL(*this);
       
   143 	if (aType==ERecover)
       
   144 		Database().Release();		// must not have any tables open during recovery
       
   145 	return CUtility::NewL(t,aType,aStep);
       
   146 	}
       
   147 
       
   148 CDbIncremental* CDbTableDatabase::CInterface::OpenExecuteL(const TDesC& aSql,TDbTextComparison aComparison,TInt& aInit)
       
   149 	{
       
   150 	switch (Sql::Type(aSql))
       
   151 		{
       
   152 	default:
       
   153 		__ASSERT(0);
       
   154 	case Sql::ENone:
       
   155 		__LEAVE(KErrArgument);
       
   156 	case Sql::EDDL:
       
   157 		{
       
   158 		CDbIncremental* inc=Sql::ParseDDLStatementLC(aSql)->ExecuteL(*this,aComparison,aInit);
       
   159 		CleanupStack::PopAndDestroy();		// statement
       
   160 		return inc;
       
   161 		}
       
   162 	case Sql::EDML:
       
   163 		{
       
   164 		CSqlDMLStatement* statement=Sql::ParseDMLStatementLC(aSql);
       
   165 		RDbTransaction& t=Database().Transaction();
       
   166 		t.DMLCheckL();			// ensure we can open a cursor
       
   167 		t.DMLPrepareL(*this);
       
   168 		CDbIncremental* inc=statement->ExecuteL(Database(),aComparison,aInit);
       
   169 		CleanupStack::PopAndDestroy();		// statement
       
   170 		return inc;
       
   171 		}
       
   172 		}
       
   173 	}
       
   174 
       
   175 //
       
   176 // Open a client-side notifier object
       
   177 //
       
   178 CDbNotifier* CDbTableDatabase::CInterface::OpenNotifierL()
       
   179 	{
       
   180 	return Database().Transaction().NotifierL();
       
   181 	}
       
   182 
       
   183 //
       
   184 // list the tables on the database
       
   185 //
       
   186 void CDbTableDatabase::CInterface::TablesL(CDbTableNames& aNames)
       
   187 	{
       
   188 	TSglQueIterC<CDbTableDef> iter(Database().SchemaL());
       
   189 	for (const CDbTableDef* def;(def=iter++)!=0;)
       
   190 		aNames.AddL(def->Name());
       
   191 	}
       
   192 
       
   193 //
       
   194 // build a column set for the table
       
   195 //
       
   196 void CDbTableDatabase::CInterface::ColumnsL(CDbColSet& aColSet,const TDesC& aName)
       
   197 	{
       
   198 	TDbCol col;
       
   199 	const HDbColumnSet& set=Database().SchemaL().FindL(aName).Columns();
       
   200 	HDbColumnSet::TIteratorC iter=set.Begin();
       
   201 	const HDbColumnSet::TIteratorC end=set.End();
       
   202 	do
       
   203 		{
       
   204 		iter->AsTDbCol(col);
       
   205 		aColSet.AddL(col);
       
   206 		} while (++iter<end);
       
   207 	}
       
   208 
       
   209 //
       
   210 // List the indexes on a table
       
   211 //
       
   212 void CDbTableDatabase::CInterface::IndexesL(CDbIndexNames& aNames,const TDesC& aTable)
       
   213 	{
       
   214 	TSglQueIterC<CDbTableIndexDef> iter(Database().SchemaL().FindL(aTable).Indexes().AsQue());
       
   215 	for (const CDbTableIndexDef* def;(def=iter++)!=0;)
       
   216 		aNames.AddL(def->Name());
       
   217 	}
       
   218 
       
   219 //
       
   220 // build a key for the index
       
   221 //
       
   222 void CDbTableDatabase::CInterface::KeysL(CDbKey& aKey,const TDesC& aName,const TDesC& aTable)
       
   223 	{
       
   224 	const CDbKey& key=Database().SchemaL().FindL(aTable).Indexes().FindL(aName).Key();
       
   225 	TInt max=key.Count();
       
   226 	for (TInt ii=0;ii<max;++ii)
       
   227 		aKey.AddL(key[ii]);
       
   228 	if (key.IsUnique())
       
   229 		aKey.MakeUnique();
       
   230 	if (key.IsPrimary())
       
   231 		aKey.MakePrimary();
       
   232 	aKey.SetComparison(key.Comparison());
       
   233 	}
       
   234 
       
   235 // Class CDbTableDatabase::CSource
       
   236 
       
   237 //
       
   238 // ctor. Add a reference to the database engine
       
   239 //
       
   240 CDbTableDatabase::CSource::CSource(CDbTableDatabase& aDatabase)
       
   241 	:iDatabase(aDatabase)
       
   242 	{
       
   243 	aDatabase.Open();
       
   244 	}
       
   245 
       
   246 //
       
   247 // dtor. remove our reference from the database engine
       
   248 //
       
   249 CDbTableDatabase::CSource::~CSource()
       
   250 	{
       
   251 	Database().Close();
       
   252 	}
       
   253 
       
   254 
       
   255 //SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method
       
   256 CDbDatabase* CDbTableDatabase::CSource::AuthenticateL()
       
   257 	{
       
   258 	Database().AuthenticateL();
       
   259 	return Database().InterfaceL();
       
   260 	}
       
   261 
       
   262 
       
   263 CDbNotifier* CDbTableDatabase::CSource::OpenNotifierL()
       
   264 	{
       
   265 	return Database().Transaction().NotifierL();
       
   266 	}
       
   267 
       
   268 // Class CDbTableDatabase
       
   269 
       
   270 EXPORT_C CDbTableDatabase::CDbTableDatabase()
       
   271 	{
       
   272 	iCache.Open();
       
   273 	iTransaction.Open(*this);
       
   274 	}
       
   275 
       
   276 EXPORT_C CDbTableDatabase::~CDbTableDatabase()
       
   277 	{
       
   278 	__ASSERT(iRef==0);
       
   279 	iTransaction.Close();
       
   280 	iTables.Close();
       
   281 	iSchema.Close();
       
   282 	iCache.Close();
       
   283 	}
       
   284 
       
   285 void CDbTableDatabase::Close()
       
   286 	{
       
   287 	__ASSERT(iRef>0);
       
   288 	if (--iRef==0)
       
   289 		delete this;
       
   290 	}
       
   291 
       
   292 //
       
   293 // Construct the implementation interface for the database framework
       
   294 // On success, the interface takes an owning reference to this
       
   295 //
       
   296 EXPORT_C CDbDatabase* CDbTableDatabase::InterfaceL()
       
   297 	{
       
   298 	return new(ELeave) CInterface(*this);
       
   299 	}
       
   300 
       
   301 //
       
   302 // Construct the implementation interface for the database framework
       
   303 // On success, the interface takes an owning reference to this
       
   304 //
       
   305 EXPORT_C CDbSource* CDbTableDatabase::SourceL()
       
   306 	{
       
   307 	return new(ELeave) CSource(*this);
       
   308 	}
       
   309 
       
   310 //
       
   311 // Load the schema if required
       
   312 //
       
   313 EXPORT_C RDbTableSchema& CDbTableDatabase::SchemaL()
       
   314 	{
       
   315 	RDbTableSchema& schema=Schema();
       
   316 	if (!schema.IsLoaded())
       
   317 		{
       
   318 		schema.Discard();
       
   319 		LoadSchemaL();
       
   320 		schema.Loaded();
       
   321 		}
       
   322 	return schema;
       
   323 	}
       
   324 
       
   325 //
       
   326 // Find any tables which are now idle, and cache them
       
   327 // Caching such a table can result in *any* table being deleted
       
   328 //  and so the iteration must restart every time an idle table is cached
       
   329 //
       
   330 void CDbTableDatabase::CheckIdle()
       
   331 	{
       
   332 	while (!iTables.IsEmpty())
       
   333 		{
       
   334 		for (TSglQueIter<CDbTable> iter(iTables);;)
       
   335 			{
       
   336 			CDbTable* table=iter++;
       
   337 			if (table==0)		// no more idle tables
       
   338 				return;
       
   339 			if (table->IsIdle())
       
   340 				{	// idle->cache transition can modify the collection
       
   341 				table->Idle();
       
   342 				break;
       
   343 				}
       
   344 			}
       
   345 		}
       
   346 	// If there are no tables left open, then the database can go idle
       
   347 	Idle();
       
   348 	}
       
   349 
       
   350 //
       
   351 // Does nothing by default
       
   352 //
       
   353 EXPORT_C void CDbTableDatabase::Idle()
       
   354 	{
       
   355     }
       
   356 
       
   357 //
       
   358 // default implementation
       
   359 //
       
   360 EXPORT_C TInt CDbTableDatabase::Property(CDbDatabase::TProperty aProperty)
       
   361 	{
       
   362 	if (aProperty<0)
       
   363 		return 0;		// utilities are not available with table database
       
   364 	__ASSERT(aProperty!=CDbDatabase::EInTransaction);
       
   365 	return KErrNotSupported;
       
   366 	}
       
   367 
       
   368 //
       
   369 // default implementation, should never be invoked
       
   370 //
       
   371 EXPORT_C CDbTableDatabase::CStepper* CDbTableDatabase::UtilityL(CDbDatabase::TUtility,TInt&)
       
   372 	{
       
   373 	__ASSERT(0);
       
   374 	return 0;
       
   375 	}
       
   376 
       
   377 void CDbTableDatabase::FlushL(TDbLockType aLock)
       
   378 	{
       
   379 	if (aLock>=EDbWriteLock)
       
   380 		{
       
   381 		TSglQueIter<CDbTable> iter(iTables);
       
   382 		for (CDbTable* table;(table=iter++)!=0;)
       
   383 			table->FlushL();
       
   384 		}
       
   385 	}
       
   386 
       
   387 void CDbTableDatabase::Abandon(TDbLockType aLock)
       
   388 	{
       
   389 	if (aLock>=EDbWriteLock)
       
   390 		{
       
   391 		TSglQueIter<CDbTable> iter(iTables);
       
   392 		for (CDbTable* table;(table=iter++)!=0;)
       
   393 			table->Abandon();
       
   394 		}
       
   395 	if (aLock==EDbSchemaLock)
       
   396 		{
       
   397 		Release();			// ensure no-one is using the old schema
       
   398 		Schema().Discard();
       
   399 		}
       
   400 	}
       
   401 
       
   402 //
       
   403 // Discard a table if it is using this definition
       
   404 //
       
   405 void CDbTableDatabase::Release(const CDbTableDef& aDef)
       
   406 	{
       
   407 	TSglQueIter<CDbTable> iter(iTables);
       
   408 	for (CDbTable* table;(table=iter++)!=0;)
       
   409 		{
       
   410 		if (&table->Def()==&aDef)
       
   411 			{
       
   412 			table->Release();
       
   413 			break;
       
   414 			}
       
   415 		}
       
   416 	}
       
   417 
       
   418 //
       
   419 // Discard all open tables as the schema has been modified or discarded
       
   420 //
       
   421 void CDbTableDatabase::Release()
       
   422 	{
       
   423 	TSglQueIter<CDbTable> iter(iTables);
       
   424 	for (CDbTable* table;(table=iter++)!=0;)
       
   425 		table->Release();
       
   426 	}
       
   427 
       
   428 //
       
   429 // Remove a table from the open set
       
   430 //
       
   431 void CDbTableDatabase::RemoveTable(CDbTable& aTable)
       
   432 	{
       
   433 	iTables.Remove(aTable);
       
   434 	if (!Transaction().IsLocked() && iTables.IsEmpty())
       
   435 		Idle();
       
   436 	}
       
   437 
       
   438 CDbTableSource* CDbTableDatabase::TableSourceL(const TDesC& aTableName)
       
   439 	{
       
   440 	CDbTableSource* rec=new(ELeave) CDbTableSource;
       
   441 	CDbTable* table=iTables.Find(aTableName);
       
   442 	if (table)
       
   443 		table->Open();		// a new reference to it
       
   444 	else
       
   445 		{
       
   446 		CleanupStack::PushL(rec);
       
   447 		table=TableL(SchemaL().FindL(aTableName));
       
   448 		CleanupStack::Pop();	// table source
       
   449 		}
       
   450 	rec->Construct(table);
       
   451 	iCache.Flush();			// check-point for object cache membership
       
   452 	return rec;
       
   453 	}
       
   454 
       
   455 //
       
   456 // Prepare the data pipeline
       
   457 //
       
   458 CDbCursor* CDbTableDatabase::PrepareViewL(const TDbQuery& aQuery,const TDbWindow& aWindow,RDbRowSet::TAccess aAccess)
       
   459 	{
       
   460 	Transaction().DMLCheckL();	// ensure we can open a cursor
       
   461 	CSqlQuery *query=Sql::ParseQueryLC(aQuery.Query());
       
   462 	RDbAccessPlan plan(query,aQuery.Comparison());
       
   463 	plan.BuildLC(*this,aAccess,aWindow);
       
   464 	CDbTableCursor* cursor=CDbTableCursor::NewL(plan,aAccess);
       
   465 	CleanupStack::Pop();			// the plan
       
   466 	CleanupStack::PopAndDestroy();	// the query
       
   467 	return cursor;
       
   468 	}
       
   469 
       
   470 //
       
   471 // Prepare the data pipeline
       
   472 //
       
   473 CDbCursor* CDbTableDatabase::PrepareTableL(const TDesC& aTable,RDbRowSet::TAccess aAccess)
       
   474 	{
       
   475 	Transaction().DMLCheckL();	// ensure we can open a cursor
       
   476 	RDbAccessPlan plan;
       
   477 	plan.BuildLC(*this,aTable,aAccess);
       
   478 	CDbTableCursor* cursor=CDbTableCursor::NewL(plan,aAccess);
       
   479 	CleanupStack::Pop();			// the plan
       
   480 	return cursor;
       
   481 	}
       
   482 
       
   483 void CDbTableDatabase::DoCreateTableL(const TDesC& aName,const CDbColSet& aColSet,const CDbKey* aPrimaryKey)
       
   484 	{
       
   485 	if (SchemaL().Find(aName))
       
   486 		__LEAVE(KErrAlreadyExists);
       
   487 // validate the colset set passed in
       
   488 	Validate::NameL(aName);
       
   489 	Validate::ColSetL(aColSet);
       
   490 	Transaction().DDLBeginLC();
       
   491 	iSchema.Add(CreateTableL(aName,aColSet,aPrimaryKey));
       
   492 	Transaction().DDLCommitL();
       
   493 	CleanupStack::Pop();		// rollback not required
       
   494 	}
       
   495 
       
   496 //
       
   497 // Create index definition and prepare to build it
       
   498 //
       
   499 CDbTableDatabase::CIncremental* CDbTableDatabase::OpenCreateIndexL(const TDesC& aName,const TDesC& aTable,const CDbKey& aKey,TInt& aStep)
       
   500 	{
       
   501 	CDbTableDef& tDef=SchemaL().FindL(aTable);
       
   502 	RDbIndexes& indexes=tDef.Indexes();
       
   503 	if (indexes.Find(aName)!=NULL)
       
   504 		__LEAVE(KErrAlreadyExists);
       
   505 	if (indexes.Count()==KDbTableMaxIndexes)
       
   506 		__LEAVE(KErrNotSupported);
       
   507 	Validate::NameL(aName);
       
   508 	Validate::KeyL(aKey,tDef.Columns());
       
   509 	if (aKey.IsPrimary())
       
   510 		__LEAVE(KErrArgument);	// cannot create a primary index
       
   511 
       
   512 	CCreateIndex* builder=CCreateIndex::NewLC(Transaction());
       
   513 	CDbTableIndexDef* xDef=CreateIndexL(tDef,aName,aKey);
       
   514 	tDef.Indexes().Add(xDef);
       
   515 	Release(tDef);				// release any table using the old schema
       
   516 	aStep=builder->ConstructL(tDef,*xDef);
       
   517 	CleanupStack::Pop();	// builder
       
   518 	return builder;
       
   519 	}
       
   520 
       
   521 //
       
   522 // Remove index from schema first, then remove index data
       
   523 //
       
   524 CDbTableDatabase::CIncremental* CDbTableDatabase::OpenDropIndexL(const TDesC& aName,const TDesC& aTable,TInt& aStep)
       
   525 	{
       
   526 	CDbTableDef& tDef=SchemaL().FindL(aTable);
       
   527 	CDbTableIndexDef& xDef=tDef.Indexes().FindL(aName);
       
   528 //
       
   529 	Release(tDef);				// release any table using the old schema
       
   530 	CDropIndex* drop=CDropIndex::NewL(Transaction(),tDef,&xDef,aStep);
       
   531 	tDef.Indexes().Remove(&xDef);
       
   532 	return drop;
       
   533 	}
       
   534 
       
   535 CDbTableDatabase::CIncremental* CDbTableDatabase::OpenDropTableL(const TDesC& aTable,TInt& aStep)
       
   536 	{
       
   537 	CDbTableDef& tDef=SchemaL().FindL(aTable);
       
   538 //
       
   539 	Release(tDef);				// release the tables using the old schema
       
   540 	CDropTable* drop=CDropTable::NewL(Transaction(),&tDef,aStep);
       
   541 	iSchema.Remove(&tDef);
       
   542 	return drop;
       
   543 	}
       
   544 
       
   545 //
       
   546 // Create an incremental table altering object
       
   547 //
       
   548 CDbTableDatabase::CIncremental* CDbTableDatabase::OpenAlterTableL(const TDesC& aTable,const CDbColSet& aNewDef,TInt& aStep)
       
   549 	{
       
   550 	CDbTableDef& tDef=SchemaL().FindL(aTable);
       
   551 	Validate::ColSetL(aNewDef);
       
   552 	Release(tDef);				// release the tables using the old schema
       
   553 	return CAlterTable::NewL(Transaction(),tDef,aNewDef,aStep);
       
   554 	}
       
   555 
       
   556 //
       
   557 // Reserved for future development
       
   558 //
       
   559 EXPORT_C void CDbTableDatabase::Reserved_1()
       
   560 	{
       
   561     }
       
   562 
       
   563 //
       
   564 // Reserved for future development
       
   565 //
       
   566 EXPORT_C void CDbTableDatabase::Reserved_2()
       
   567 	{
       
   568     }