epoc32/include/sqldb.h
branchSymbian3
changeset 4 837f303aceeb
parent 2 2fe1408b6811
--- a/epoc32/include/sqldb.h	Wed Mar 31 12:27:01 2010 +0100
+++ b/epoc32/include/sqldb.h	Wed Mar 31 12:33:34 2010 +0100
@@ -1,9 +1,9 @@
 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
-// under the terms of the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members
+// under the terms of "Eclipse Public License v1.0"
 // which accompanies this distribution, and is available
-// at the URL "http://www.symbianfoundation.org/legal/licencesv10.html".
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
 //
 // Initial Contributors:
 // Nokia Corporation - initial contribution.
@@ -15,8 +15,6 @@
 // 
 //
 
-
-
 /**
  @file
  @publishedAll
@@ -29,6 +27,10 @@
 #include <s32std.h>	//RReadStream, RWriteStream
 #endif
 
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS 
+	#include <sqlresourcetester.h>
+#endif
+
 //Forward declarations
 class CSqlSecurityPolicy;
 class RSqlDatabase;
@@ -38,6 +40,24 @@
 class RSqlColumnReadStream;
 class RSqlParamWriteStream;
 class TSqlScalarFullSelectQuery;
+class RSqlBlob;
+class RSqlBlobReadStream;
+class RSqlBlobWriteStream;
+class TSqlResourceProfiler;
+
+/**
+Used to specify that the ROWID of the most recently inserted record
+from the specified database connection should be used as the ROWID 
+in a call to directly access a blob.
+
+@see RSqlBlobReadStream
+@see RSqlBlobWriteStream
+@see TSqlBlob
+
+@publishedAll
+@released
+*/
+const TInt KSqlLastInsertedRowId = -1;
 
 /**
 A container for the security policies for a shared SQL database.
@@ -228,6 +248,8 @@
 - attach a SQL database to current database connection by calling RSqlDatabase::Attach().
 - detach a SQL database from current database connection by calling RSqlDatabase::Detach().
 
+The RSqlDatabase handles are not thread-safe.
+
 A client can create either a non-secure database or a secure database,
 depending on the variant of RSqlDatabase::Create() that is used.
 - a non-secure database is created if the RSqlDatabase::Create(const TDesC&) variant is used.
@@ -281,6 +303,10 @@
 	{
 	friend class RSqlStatement;
 	friend class TSqlScalarFullSelectQuery;
+	friend class RSqlBlob;
+	friend class RSqlBlobReadStream;
+	friend class RSqlBlobWriteStream;
+	friend class TSqlResourceProfiler;
 	
 public:
 	/**
@@ -377,6 +403,20 @@
 		*/
 		ESerializable
 		};
+	/**
+	This structure is used for retrieving the database size and database free space.
+	@see RSqlDatabase::Size(TSize&)
+	*/
+	struct TSize
+		{
+		/** The database size in bytes*/
+		TInt64	iSize;
+		/** The database free space in bytes*/
+		TInt64	iFree;
+		};
+
+	/** If this value is used as an argument of RSqlDatabase::Compact() (aSize argument), then all free space will be removed */
+	enum {EMaxCompaction = -1};
 		
 	IMPORT_C RSqlDatabase();
 	
@@ -409,9 +449,14 @@
 	IMPORT_C void Exec(const TDesC8& aSqlStmt, TRequestStatus& aStatus);
 	
 	IMPORT_C TPtrC LastErrorMessage() const;
+	IMPORT_C TInt64 LastInsertedRowId() const; 
 	
 	IMPORT_C TBool InTransaction() const;
 	IMPORT_C TInt Size() const;
+	IMPORT_C TInt Size(TSize& aSize, const TDesC& aDbName = KNullDesC) const;
+
+	IMPORT_C TInt Compact(TInt64 aSize, const TDesC& aDbName = KNullDesC);
+	IMPORT_C void Compact(TInt64 aSize, TRequestStatus& aStatus, const TDesC& aDbName = KNullDesC);
 	
 	IMPORT_C TInt ReserveDriveSpace(TInt aSize);
 	IMPORT_C void FreeReservedSpace();
@@ -541,7 +586,7 @@
 	/**
 	Binary data, a sequence of bytes.
 	*/
-	ESqlBinary 
+	ESqlBinary
 	};
 
 /**
@@ -761,10 +806,18 @@
 If the result is outside the range that can be represented by the type returned
 by the accessor function, then it will be clamped.
 
+Note that when handling blob and text data over 2Mb in size it is recommended that the 
+RSqlBlobReadStream and RSqlBlobWriteStream classes or the TSqlBlob class is used instead. 
+These classes provide a more RAM-efficient way of reading and writing large amounts of 
+blob or text data from a database.
+
 @see KMinTInt
 @see KMaxTInt
 @see KNullDesC
 @see KNullDesC8
+@see RSqlBlobReadStream
+@see RSqlBlobWriteStream
+@see TSqlBlob
 
 @publishedAll
 @released
@@ -800,6 +853,7 @@
 	IMPORT_C TInt BindReal(TInt aParameterIndex, TReal aParameterValue);
 	IMPORT_C TInt BindText(TInt aParameterIndex, const TDesC& aParameterText);
 	IMPORT_C TInt BindBinary(TInt aParameterIndex, const TDesC8& aParameterData);
+	IMPORT_C TInt BindZeroBlob(TInt aParameterIndex, TInt aBlobSize);
 	
 	IMPORT_C TBool IsNull(TInt aColumnIndex) const;
 	IMPORT_C TInt ColumnInt(TInt aColumnIndex) const;
@@ -814,6 +868,9 @@
 	IMPORT_C TInt ColumnBinary(TInt aColumnIndex, TPtrC8& aPtr) const;
 	IMPORT_C TInt ColumnBinary(TInt aColumnIndex, TDes8& aDest) const;
 	
+	IMPORT_C TInt ColumnName(TInt aColumnIndex, TPtrC& aNameDest);
+	IMPORT_C TInt ParameterName(TInt aParameterIndex, TPtrC& aNameDest);
+	IMPORT_C TInt ParamName(TInt aParameterIndex, TPtrC& aNameDest);
 private:
 	CSqlStatementImpl& Impl() const;
 	
@@ -825,13 +882,18 @@
 /**
 The read stream interface.
 
-The class is used for reading the content of a column containing a large
-amount of either binary data or text data.
+The class is used for reading the content of a column containing either 
+binary data or text data.
 
 The class derives from RReadStream, which means that all RReadStream public
 member functions and predefined stream operators \>\> can be used to deal
 with column data.
 
+If the blob or text data is over 2Mb in size then it is recommended that the 
+RSqlBlobReadStream or TSqlBlob class is used instead. These classes provide 
+a more RAM-efficient way of reading large amounts of blob or text data from
+a database.
+
 The following two cases are typical:
 
 CASE 1 - processing large binary column data.
@@ -886,6 +948,9 @@
 	}
 @endcode
 
+@see RSqlBlobReadStream
+@see TSqlBlob
+
 @publishedAll
 @released
 */
@@ -902,13 +967,18 @@
 /**
 The write stream interface.
 
-The class is used to set a large amount of either binary data or text data
-into a parameter. This is a also known as binding a parameter.
+The class is used to set binary data or text data into a parameter. 
+This is a also known as binding a parameter.
 
 The class derives from RWriteStream, which means that all RWriteStream public
 member functions and predefined stream operators \<\< can be used to deal with
 the parameter data.
 
+If the blob or text data is over 2Mb in size then it is recommended that the 
+RSqlBlobWriteStream or TSqlBlob class is used instead. These classes provide 
+a more RAM-efficient way of writing large amounts of blob or text data to
+a database.
+
 The following two cases are typical:
 
 CASE 1 - binding a large binary parameter.
@@ -955,6 +1025,9 @@
 CleanupStack::PopAndDestroy(&paramStream);
 @endcode
 
+@see RSqlBlobWriteStream
+@see TSqlBlob
+
 @publishedAll
 @released
 */
@@ -969,22 +1042,312 @@
 	};
 
 /**
-TSqlResourceTester class is used internally by the SQL server out of memory and resource leaking
-tests. 
-It provides methods for heap allocation failure simulation and resource checking and counting.
+A direct handle to a blob, used for reading the content of the blob via a streaming interface.
+
+The target blob is identified using the relevant database connection, table name, 
+column name and ROWID of the record to which the blob belongs (also the attached
+database name if the blob is contained in an attached database).
+
+A blob in this context refers to the content of a BLOB or TEXT column, 
+and a read handle can be opened on both types of column.
+For TEXT columns it is important to note that no conversions are performed on 
+data retrieved using this class - the data is returned as a stream of bytes.
+
+The class derives from RReadStream and provides all of its streaming methods.
+The SizeL() method can be used to check the total size of the blob, in bytes.
+
+It is strongly recommended to use this class for reading the content of large blobs 
+because it significantly reduces the amount of RAM that is used when compared to using the 
+RSqlColumnReadStream, RSqlStatement::ColumnBinary(L) or RSqlStatement::ColumnText(L) APIs.
+
+Specifically, it is recommended to use this class for blobs over 2Mb in size.
+Indeed, in some circumstances where very large blobs are in use it may be impossible
+to read the blob content using the legacy APIs (due to the server's finite RAM capacity), 
+and this class may provide the only way to access the data.
+
+The following code illustrates typical use cases of this class:
+
+CASE 1 - reading large blob data from the last inserted record.
 
-@internalAll
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+RSqlBlobReadStream rdStrm;
+CleanupClosePushL(rdStrm);
+rdStrm.OpenL(db, <table_name>, <column_name>);
+HBufC8* buffer = HBufC8::NewLC(KBlockSize);
+TPtr8 bufPtr(buffer->Des());
+TInt size = rdStrm.SizeL();
+while(size)
+	{
+	TInt bytesToRead = (size >= KBlockSize) ? KBlockSize : size ;
+	rdStrm.ReadL(bufPtr, bytesToRead); // read the next block of data		
+	<do something with the block of data>
+	size =- bytesToRead;
+	}
+CleanupStack::PopAndDestroy(3); // buffer, rdStrm, db
+@endcode
+
+CASE 2 - reading large blob data from a selection of records.
+
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+RSqlStatement stmt;
+CleanupClosePushL(stmt);
+<prepare "stmt" object to SELECT the ROWIDs of a collection of blob objects>;
+TInt rc = 0;
+while((rc = stmt.Next()) == KSqlAtRow)
+	{
+	TInt64 rowid = stmt.ColumnInt64(0);	
+	RSqlBlobReadStream rdStrm;
+	CleanupClosePushL(rdStrm);
+	rdStrm.OpenL(db, <table_name>, <column_name>, rowid);
+	
+	HBufC8* buffer = HBufC8::NewLC(KBlockSize);
+	TPtr8 bufPtr(buffer->Des());
+	TInt size = rdStrm.SizeL();
+	while(size)
+		{
+		TInt bytesToRead = (size >= KBlockSize) ? KBlockSize : size ;
+		rdStrm.ReadL(bufPtr, bytesToRead); // read the next block of data		
+		<do something with the block of data>
+		size =- bytesToRead;
+		}
+	CleanupStack::PopAndDestroy(2); // buffer, rdStrm
+	}
+CleanupStack::PopAndDestroy(2); // stmt, db
+@endcode
+
+@see RSqlBlobWriteStream
+@see RSqlDatabase::LastInsertedRowId()
+
+@publishedAll
 @released
 */
-class TSqlResourceTester
+class RSqlBlobReadStream : public RReadStream
+	{
+public:						
+	IMPORT_C void OpenL(RSqlDatabase& aDb, const TDesC& aTableName, const TDesC& aColumnName, 
+						TInt64 aRowId = KSqlLastInsertedRowId, const TDesC& aDbName = KNullDesC);
+	IMPORT_C TInt SizeL();
+	};
+
+/**
+A direct handle to a blob, used for writing the content of the blob via a streaming interface.
+
+The target blob is identified using the relevant database connection, table name, 
+column name and ROWID of the record to which the blob belongs (also the attached
+database name if the blob is contained in an attached database).
+
+A blob in this context refers to the content of a BLOB or TEXT column, 
+and a write handle can be opened on both types of column, except if the
+column is indexed, in which case the open call will fail with KSqlErrGeneral.
+For TEXT columns it is important to note that no conversions are performed on data 
+that is stored using this class - the data is simply stored as a stream of bytes.
+
+The class derives from RWriteStream and provides all of its streaming methods.
+The SizeL() method can be used to check the total size of the blob, in bytes.
+Note that this class cannot be used to increase the size of a blob, only to modify 
+the existing contents of a blob. An attempt to write beyond the end of a blob will
+fail with KErrEof.
+
+It is strongly recommended to use this class for writing the content of large blobs 
+because it significantly reduces the amount of RAM that is used when compared to using 
+the RSqlParamWriteStream, RSqlStatement::BindBinary or RSqlStatement::BindText APIs.
+
+Specifically, it is recommended to use this class for blobs over 2Mb in size.
+Indeed, in some circumstances where very large blobs are required it may be impossible
+to create a blob or update its content using the legacy APIs (due to the server's finite 
+RAM capacity), and this class may provide the only way to achieve this.
+
+Using this class in combination with zeroblobs it is possible to create and manipulate 
+blobs that are gigabytes in size. A zeroblob acts as a place-holder for a blob whose 
+content is later written using this class and one can be created using an INSERT 
+statement that either contains the SQLite 'zeroblob()' function or on which 
+RSqlStatement::BindZeroBlob() has been executed.
+Note that a zeroblob should be created in a column after which there are no columns 
+that contain anything other than zeroblobs or NULLs, otherwise the zeroblob must be 
+allocated in full in RAM.
+
+When creating a zeroblob it is recommended, where possible, to create the zeroblob and
+then write the blob content within the same transaction. Otherwise the zeroblob will 
+have to be journalled before being written to.
+
+It is also strongly recommended to execute calls to WriteL() within a transaction. 
+If a leave occurs during a call to WriteL() then the current state of the blob object is
+undefined and a ROLLBACK should be executed to return the blob object to its previous state.
+Note that in order for a ROLLBACK to execute successfully all open RSqlBlobReadStream 
+and RSqlBlobWriteStream handles and all open RSqlStatement objects must be closed 
+before the ROLLBACK is executed.
+
+The following code illustrates typical use cases of this class:
+
+CASE 1 - creating a 5Mb blob.
+
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+CleanupStack::PushL(TCleanupItem(&DoRollback, &db)); // rollback function
+TInt err = db.Exec(_L("BEGIN"));
+<check err>
+err = db.Exec(_L("INSERT INTO table1 VALUES(35, zeroblob(5242880))"));
+<check err>
+RSqlBlobWriteStream wrStrm;
+CleanupClosePushL(wrStrm);
+wrStrm.OpenL(db, <table_name>, <column_name>);
+TInt size = wrStrm.SizeL();
+while(size)
 	{
-public:	
-	IMPORT_C static void Mark();
-	IMPORT_C static void Check();
-	IMPORT_C static TInt Count();
-	IMPORT_C static void SetDbHeapFailure(TInt aAllocFailType,TInt aRate);
-	IMPORT_C static void SetHeapFailure(TInt aAllocFailType,TInt aRate);
+	TInt bytesToWrite = (size >= KBlockSize) ? KBlockSize : size ;
+	<fill a buffer 'buf' with this amount of the blob data>
+	wrStrm.WriteL(buf); // write the next block of data		
+	size =- bytesToWrite;
+	}
+CleanupStack::PopAndDestroy(&wrStrm);
+CleanupStack::Pop(); // TCleanupItem
+err = db.Exec(_L("COMMIT")); // blob data committed to disk
+<check err>
+CleanupStack::PopAndDestroy(&db);
+@endcode
+
+CASE 2 - updating a large blob in the last inserted record.
+
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+CleanupStack::PushL(TCleanupItem(&DoRollback, &db)); // rollback function
+TInt err = db.Exec(_L("BEGIN"));
+<check err>
+RSqlBlobWriteStream wrStrm;
+CleanupClosePushL(wrStrm);
+wrStrm.OpenL(db, <table_name>, <column_name>);
+<fill a buffer 'buf' with the changed blob data>
+wrStrm.WriteL(buf); // update the blob
+CleanupStack::PopAndDestroy(&wrStrm);
+CleanupStack::Pop(); // TCleanupItem
+err = db.Exec(_L("COMMIT")); // blob data committed to disk
+<check err>
+CleanupStack::PopAndDestroy(&db);
+@endcode
+
+@see RSqlBlobReadStream
+@see RSqlDatabase::LastInsertedRowId()
+@see RSqlStatement::BindZeroBlob()
+
+@publishedAll
+@released
+*/
+class RSqlBlobWriteStream : public RWriteStream
+	{
+public:
+	IMPORT_C void OpenL(RSqlDatabase& aDb, const TDesC& aTableName, const TDesC& aColumnName, 
+						TInt64 aRowId = KSqlLastInsertedRowId, const TDesC& aDbName = KNullDesC);
+	IMPORT_C TInt SizeL();
+	};
+
+/**
+Utility class that provides methods for reading and writing the entire content of 
+a blob in a single call.
+
+The target blob is identified using the relevant database connection, table name, 
+column name and ROWID of the record to which the blob belongs (also the attached
+database name if the blob is contained in an attached database).
+
+The behaviour of the RSqlBlobReadStream class and the recommendations for using
+it exist for the Get() and GetLC() methods of this class. Similarly, the behaviour 
+of the RSqlBlobWriteStream class and the recommendations for using it exist for the 
+SetL() method of this class.
+
+In particular, it is strongly recommended to use this class or the RSqlBlobReadStream
+and RSqlBlobWriteStream classes for reading and writing the content of large blobs 
+because it significantly reduces the amount of RAM that is used when compared to using 
+the legacy streaming and RSqlStatement APIs.
+
+Specifically, it is recommended to use this class for blobs over 2Mb in size.
+Indeed, in some circumstances where very large blobs are in use it may be impossible
+to read or write to a blob using the legacy APIs (due to the server's finite 
+RAM capacity), and this class or the RSqlBlobReadStream and RSqlBlobWriteStream classes 
+may provide the only way to achieve this.
 
+It is strongly recommended to execute calls to the SetL() method within a transaction. 
+If a leave occurs during a call to SetL() then the current state of the blob object is 
+undefined and a ROLLBACK should be executed to return the blob object to its previous state.
+Note that in order for a ROLLBACK to execute successfully all open RSqlBlobReadStream 
+and RSqlBlobWriteStream handles and all open RSqlStatement objects must be closed 
+before the ROLLBACK is executed.
+
+When using SetL() to update the content of a zeroblob it is recommended, where possible, 
+to create the zeroblob and then call SetL() within the same transaction. 
+Otherwise the zeroblob will have to be journalled before being written to.
+
+The following code illustrates typical use cases of this class:
+
+CASE 1 - retrieving the entire content of a large blob.
+
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+HBufC8* wholeBlob = TSqlBlob::GetLC(db, <table_name>, <column_name>, <rowid>);
+<do something with the blob data>
+CleanupStack::PopAndDestroy(2); // wholeBlob, db
+@endcode
+
+
+CASE 2 - creating a 4Mb blob.
+
+@code
+RSqlDatabase db;
+CleanupClosePushL(db);
+<open/create "db" object>;
+CleanupStack::PushL(TCleanupItem(&DoRollback, &db)); // rollback function
+TInt err = db.Exec(_L("BEGIN"));
+<check err>
+err = db.Exec(_L("INSERT INTO table1 VALUES(99, zeroblob(4194304))"));
+<check err>
+<fill a buffer 'buf' with 4Mb of blob data>
+TSqlBlob::SetL(db, <table_name>, <column_name>, buf);
+CleanupStack::Pop(); // TCleanupItem
+err = db.Exec(_L("COMMIT")); // blob data committed to disk
+<check err>
+CleanupStack::PopAndDestroy(&db);
+@endcode
+
+@see RSqlBlobReadStream
+@see RSqlBlobWriteStream
+@see RSqlDatabase::LastInsertedRowId()
+@see RSqlStatement::BindZeroBlob()
+
+@publishedAll
+@released
+*/
+class TSqlBlob
+	{
+public:					  		  	  
+	IMPORT_C static HBufC8* GetLC(RSqlDatabase& aDb, 	
+					     		  const TDesC& aTableName, 
+					     		  const TDesC& aColumnName, 	
+					     		  TInt64 aRowId = KSqlLastInsertedRowId,
+					     		  const TDesC& aDbName = KNullDesC);
+								  		  	  
+	IMPORT_C static TInt Get(RSqlDatabase& aDb, 	
+					 		 const TDesC& aTableName, 
+					 		 const TDesC& aColumnName, 	
+					 		 TDes8& aBuffer,
+					 		 TInt64 aRowId = KSqlLastInsertedRowId,
+					 		 const TDesC& aDbName = KNullDesC);			 		 
+
+	IMPORT_C static void SetL(RSqlDatabase& aDb, 	
+					  		  const TDesC& aTableName, 
+					  		  const TDesC& aColumnName,
+					  		  const TDesC8& aData,	
+					  		  TInt64 aRowId = KSqlLastInsertedRowId,
+					  		  const TDesC& aDbName = KNullDesC);				  
 	};
 
 /**