diff -r 000000000000 -r 08ec8eefde2f persistentstorage/dbms/pcdbms/udbms/UD_DBS.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/dbms/pcdbms/udbms/UD_DBS.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,573 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "UD_STD.H" + +// Class RDbDatabase + +/** +Closes a database. Commits any pending transaction. Frees the allocated resources. +*/ +EXPORT_C void RDbDatabase::Close() + { + CDbDatabase* db=iDatabase(); + if (db && InTransaction()) + Commit(); // attempt to commit + iDatabase.Close(); + } + +// +// Runs the incremental DDL object to completion. +// +LOCAL_C void CompleteDDLL(CDbIncremental* aIncremental,TInt& aStep) + { + __ASSERT((aIncremental==0)==(aStep==0)); + if (!aIncremental) + return; + aIncremental->PushL(); + do aIncremental->NextL(aStep); + while (aStep!=0); + CleanupStack::PopAndDestroy(); // aIncrmental + } + +// +// Runs the DML incremental object to completion. +// +LOCAL_C void CompleteDMLL(CDbIncremental* aIncremental,TInt& aRows) + { + __ASSERT((aIncremental==0)!=(aRows==0)); + if (!aIncremental) + return; + aIncremental->PushL(); + while (aIncremental->NextL(aRows)) + ; + CleanupStack::PopAndDestroy(); // aIncremental + } + +LOCAL_C TInt Property(const RDbHandle& aDb,CDbDatabase::TProperty aProperty) + { + return aDb->Property(aProperty); + } + +LOCAL_C TInt Utility(RDbHandle& aDb,CDbDatabase::TUtility aType) + { + TInt step; + TRAPD(r,CompleteDDLL(aDb->UtilityL(aType,step),step)); + return r; + } + +/** +Reports the damage status of the database. +The function checks database indexes and returs true if some of them are broken. + +@return True if the database is damaged, false otherwise. +*/ +EXPORT_C TBool RDbDatabase::IsDamaged() const + { + return Property(iDatabase,CDbDatabase::EIsDamaged); + } + +/** +Synchronous database recovery. +Recover() will try to rebuild database indexes if they are broken. +If the database data is corrupted, it cannot be recovered. + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the write + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::Recover() + { + return Utility(iDatabase,CDbDatabase::ERecover); + } + +/** +Returns the currently available size information for the database. +This comprises a size in bytes for the database objects and a percentage used value which indicates +how much of that size is live data-the remainder may be available for compaction. +Some types of database may not be able to report this information, e.g. a RDbStoreDatabase, +and others may need to have UpdateStats() in order to provide valid data. +In these cases, the values in the RDbDatabase::TSize structure will contain an error value to indicate this. + +@return RDbDatabase::TSize object, containing the database size and the percentage used value. +*/ +EXPORT_C RDbDatabase::TSize RDbDatabase::Size() const + { + TSize size; + size.iSize=Property(iDatabase,CDbDatabase::ESize); + size.iUsage=Property(iDatabase,CDbDatabase::EUsage); + return size; + } + +/** +Update any calculated statistics for the database. +Note that this can take an extended time to complete, +so an incremental form is also provided - RDbIncremental::UpdateStats(). + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the write + access policy for the database. + +@see RDbIncremental::UpdateStats() +*/ +EXPORT_C TInt RDbDatabase::UpdateStats() + { + return Utility(iDatabase,CDbDatabase::EStats); + } + +/** +Synchronous database compaction. +Compacts the database and returns when complete. +Note that this can take an extended time to complete, so an incremental form is also provided. +There is a complementary interface to calculate and report database size and usage information, which +can be used by the clients to determine when it may be appropriate to compact the database. + +@see RDbIncremental::Compact() +@see RDbDatabase::UpdateStats() +@see RDbDatabase::Size() + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the write + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::Compact() + { + return Utility(iDatabase,CDbDatabase::ECompact); + } + + +/** +Drops the tables and destroys the database. +This handle is closed on successful destruction. + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::Destroy() + { + CDbTableNames* t=NULL; + TRAPD(r,t=TableNamesL()); + if (r!=KErrNone) + return r; + TInt ii=t->Count(); + do + { + if (--ii<0) + { + r=iDatabase->Destroy(); + if (r==KErrNone) + iDatabase.Close(); + break; + } + r=DropTable((*t)[ii]); + } while (r==KErrNone); + delete t; + return r; + } + +/** +Begins a transaction. + +DBMS server only supports one 'granularity' of transaction lock: the whole database. +Beginning a transaction locks the database, and this can fail if another client has already got a lock which +excludes this client. +If the same client has already locked the database it will be panic'd. +The function is guaranteed to return KErrNone for client-side access. + +DBMS transactions do not provide any form of isolation between the clients: +while one client is updating a table within a transaction, other clients will be able to see the changes as +they are made. As a result, if a client retrieves two separate rows from a database there is no automatic +guarantee that the data being retrieved has not been changed between the reads - this can lead to +an 'inconsistent read'. A client can prevent an update while retrieving related rows by enclosing the individual +reads within a transaction. Such a transaction will not modify the database and only operates as a read-lock: +releasing such a lock using Commit() or Rollback() will not affect the database in any way. + +How RDbDatabase::Begin() works: + - on a shared database Begin() will attempt to get a shared read-lock on the database, and will fail with + KErrLocked if anyone has an exclusive write-lock. Other clients with read-locks will not cause this operation + to fail. + - any operation which will modify the database attempts to gain an exclusive write-lock on the database, + and will fail with KErrLocked if anyone else has any lock on the database. If the current client already has + a read-lock as a result of calling Begin(), then it will be upgraded to an exclusive write-lock. + - Commit() or Rollback() after a read-lock has been acquired (but not a write-lock) will release that client's + lock. The database will only be considered to be unlocked when all such locks are removed by all clients, + when it will report a EUnlock event to any notifiers. + - Commit() or Rollback() after a write-lock has been acquired will release the lock, and report the ECommit or + ERollback event to any notifiers. + - automatic transactions will be used as at present if updates are made outside of explicit transactions, + and such updates will also be able to fail with KErrLocked if an exclusive lock cannot be acquired. + +Allowing read-locks to be shared enables greater concurrency at the same time as providing some safe guard +against inconsistent reads. It does, however, lead to the possibility of deadlock: two clients wanting to update +the database can reach deadlock if they both Begin() a transaction before either of them starts an update, +then one client's read-lock will prevent the other from upgrading to a write lock and vice versa. The only way out +of this is to code the clients in such a way as to back out of such a deadlock situation, rather than retry +forever without releasing the locks. + +A client will be able to change the database schema while other clients are using the database, +as long as the other clients have no locks on it. As described above, other clients may find that their +rowsets are then invalidated asynchronously as a result of this. + +@return KErrNone The operation has completed successfully; + KErrLocked, the database is locked by another client; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy either the read, write + or the schema access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::Begin() + { + return iDatabase->Begin(); + } + +/** +Commits the current transaction. + +@return KErrNone The operation has completed successfully; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy either the read, write + or the schema access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::Commit() + { + return iDatabase->Commit(); + } + +/** +Rollbacks the current transaction. + +@capability Note For a secure shared database, the caller must satisfy either the read, write + or the schema access policy for the database. +*/ +EXPORT_C void RDbDatabase::Rollback() + { + iDatabase->Rollback(); + } + +/** +@return True if the database is in a transaction, false otherwise. +*/ +EXPORT_C TBool RDbDatabase::InTransaction() const + { + return Property(iDatabase,CDbDatabase::EInTransaction); + } + +/** +Creates a table on the database. + +@param aName Table name. +@param aColSet A set of column definitions which describe the table structure. +@param aPrimaryKey Primary key definition. If it is NULL, no primary key will be created for the new table. + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrAlreadyExists, a table with that name already exists; + KErrArgument, empty column set, duplicated column name, invalid column length; + KErrBadName, invalid table name, invalid column name (containing spaces for example); + KErrNotSupported, unknown column type, unknown column attributes; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::CreateTable(const TDesC& aName,const CDbColSet& aColSet,const CDbKey* aPrimaryKey) + { + TRAPD(r,iDatabase->CreateTableL(aName,aColSet,aPrimaryKey)); + return r; + } + +/** +Drops a table synchronously. + +@param aName Table name. + +@return KErrNone The operation has completed successfully; + KErrNotFound, there is no table with the supplied name; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::DropTable(const TDesC& aName) + { + TInt step; + TRAPD(r,CompleteDDLL(iDatabase->DropTableL(aName,step),step)); + return r; + } + +/** +Alters a table synchronously. + +@param aName Table name. +@param aColSet A new set of column definitions which describe the table structure. + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrArgument, empty column set, duplicated column name, invalid column length; + KErrNotFound, there is no table with the supplied name; + KErrNotSupported, unknown column type, unknown column attributes; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::AlterTable(const TDesC& aName,const CDbColSet& aColSet) + { + TInt step; + TRAPD(r,CompleteDDLL(iDatabase->AlterTableL(aName,aColSet,step),step)); + return r; + } + +/** +Creates an index synchronously. + +@param aName Index name. +@param aTableName Table name. +@param aKey Index definition + +@return KErrNone The operation has completed successfully; + KErrNoMemory, an out of memory condition has occurred; + KErrBadName, invalid index name (containing spaces for example); + KErrAlreadyExists, an index with that name already exists; + KErrNotFound, there is no table with that name; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::CreateIndex(const TDesC& aName,const TDesC& aTableName,const CDbKey& aKey) + { + TInt step; + TRAPD(r,CompleteDDLL(iDatabase->CreateIndexL(aName,aTableName,aKey,step),step)); + return r; + } + +/** +Drops an index synchronously. + +@param aName Index name. +@param aTableName Table name. + +@return KErrNone The operation has completed successfully; + KErrNotFound, there is no table or index with that name; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy the schema + access policy for the database. +*/ +EXPORT_C TInt RDbDatabase::DropIndex(const TDesC& aName,const TDesC& aTableName) + { + TInt step; + TRAPD(r,CompleteDDLL(iDatabase->DropIndexL(aName,aTableName,step),step)); + return r; + } + +/** +Executes a SQL statement on the database, and returns when it is complete. +The aComp parameter is used in the execution of some SQL statements: + - in CREATE INDEX statements it specifies the comparison operation used for text columns in the index key; + - in UPDATE and DELETE statements it specifies the comparison operation used to evaluate the WHERE clause; +Other statements ignore the value of aComp. +A negative return value indicates an error. A successful DDL operation always returns KErrNone (zero), +a successful DML operation returns the number of rows that were inserted, updated or deleted by the operation. + +@param aSql A string of 16-bit wide characters containing one SQL statement. +@param aComparison Tells the DBMS how to compare text and long text columns. + +@return Zero or positive value, the number of rows that were inserted, updated or deleted by the operation; + KErrLocked, the database is locked by another client; + KErrPermissionDenied, the caller does not satisfy the relevant database security policies. + Note that other system-wide error codes may also be returned. + +@capability Note For a secure shared database, the caller must satisfy: + - the schema access policy for the database, if the SQL statement is + CREATE/DROP/ALTER; + - the write access policy for the table in the SQL, if the SQL statement is + INSERT/UPDATE/DELETE; +*/ +EXPORT_C TInt RDbDatabase::Execute(const TDesC& aSql,TDbTextComparison aComparison) + { + TInt ret; + TRAP(ret, \ + CDbIncremental* inc=iDatabase->ExecuteL(aSql,aComparison,ret); \ + if (inc) \ + ret ? CompleteDDLL(inc,ret) : CompleteDMLL(inc,ret); \ + ) + return ret; + } + +/** +Lists the tables on the database. + +@return A pointer to a CDbTableNames container with table names. The caller is responsible for destroying + the returned CDbTableNames instance. + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with other system-wide error codes. +*/ +EXPORT_C CDbTableNames* RDbDatabase::TableNamesL() const + { + CDbTableNames* names=CDbTableNames::NewLC(); + iDatabase->TablesL(*names); + CleanupStack::Pop(); + return names; + } + +/** +Returns the table definition. + +@param aName Table name. + +@return A pointer to a CDbColSet container with column definitions . The caller is responsible for destroying + the returned CDbColSet instance. + +@leave KErrNoMemory, an out of memory condition has occurred; + KErrNotFound, no table with that name exists; + Note that the function may leave with other system-wide error codes. +*/ +EXPORT_C CDbColSet* RDbDatabase::ColSetL(const TDesC& aName) const + { + CDbColSet* set=CDbColSet::NewLC(); + iDatabase->ColumnsL(*set,aName); + CleanupStack::Pop(); + return set; + } + +/** +Lists the indexes on a table. + +@param aTable Table name. + +@return A pointer to a CDbIndexNames container with column definitions . The caller is responsible for destroying + the returned CDbIndexNames instance. + +@leave KErrNoMemory, an out of memory condition has occurred; + KErrNotFound, no table with that name exists; + Note that the function may leave with other system-wide error codes. +*/ +EXPORT_C CDbIndexNames* RDbDatabase::IndexNamesL(const TDesC& aTable) const + { + CDbIndexNames* names=CDbIndexNames::NewLC(); + iDatabase->IndexesL(*names,aTable); + CleanupStack::Pop(); + return names; + } + +/** +Returns the index key. + +@param aName Index name. +@param aTable Table name. + +@return A pointer to a CDbKey object containing the index definition. The caller is responsible for destroying + the returned CDbKey instance. + +@leave KErrNoMemory, an out of memory condition has occurred; + KErrNotFound, no index or table with that name exists; + Note that the function may leave with other system-wide error codes. +*/ +EXPORT_C CDbKey* RDbDatabase::KeyL(const TDesC& aName,const TDesC& aTable) const + { + CDbKey* key=CDbKey::NewLC(); + iDatabase->KeysL(*key,aName,aTable); + CleanupStack::Pop(); + return key; + } + +// class CDbDatabase + +CDbNotifier* CDbDatabase::NotifierL() + { + return AttachContext(this,OpenNotifierL()); + } + +CDbIncremental* CDbDatabase::UtilityL(CDbDatabase::TUtility aType,TInt& aStep) + { + return AttachContext(this,OpenUtilityL(aType,aStep)); + } + +CDbIncremental* CDbDatabase::DropTableL(const TDesC& aTable,TInt& aStep) + { + return AttachContext(this,OpenDropTableL(aTable,aStep)); + } + +CDbIncremental* CDbDatabase::AlterTableL(const TDesC& aTable,const CDbColSet& aNewDef,TInt& aStep) + { + return AttachContext(this,OpenAlterTableL(aTable,aNewDef,aStep)); + } + +CDbIncremental* CDbDatabase::CreateIndexL(const TDesC& aName,const TDesC& aTable,const CDbKey& aKey,TInt& aStep) + { + return AttachContext(this,OpenCreateIndexL(aName,aTable,aKey,aStep)); + } + +CDbIncremental* CDbDatabase::DropIndexL(const TDesC& aName,const TDesC& aTable,TInt& aStep) + { + return AttachContext(this,OpenDropIndexL(aName,aTable,aStep)); + } + +CDbIncremental* CDbDatabase::ExecuteL(const TDesC& aSql,TDbTextComparison aComparison,TInt& aInit) + { + return AttachContext(this,OpenExecuteL(aSql,aComparison,aInit)); + } + +CDbCursor* CDbDatabase::ViewL(const TDbQuery& aQuery,const TDbWindow& aWindow,RDbRowSet::TAccess anAccess) + { + return AttachContext(this,PrepareViewL(aQuery,aWindow,anAccess)); + } + +CDbCursor* CDbDatabase::TableL(const TDesC &aName,RDbRowSet::TAccess anAccess) + { + return AttachContext(this,OpenTableL(aName,anAccess)); + } + +// +// Reserved for future development +// +EXPORT_C void CDbDatabase::Reserved_1() + { + } + +// +// Reserved for future development +// +EXPORT_C void CDbDatabase::Reserved_2() + { + }