persistentstorage/sql/INC/SqlDb.h
changeset 0 08ec8eefde2f
child 10 fa9941cf3867
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/INC/SqlDb.h	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1758 @@
+// 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 "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:
+// SQL Client side API header
+// 
+//
+
+/**
+ @file
+ @publishedAll
+ @released
+*/
+#ifndef __SQLDB_H__
+#define __SQLDB_H__
+
+#ifndef __S32STD_H__
+#include <s32std.h>	//RReadStream, RWriteStream
+#endif
+
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS 
+	#include <sqlresourcetester.h>
+#endif
+
+//Forward declarations
+class CSqlSecurityPolicy;
+class RSqlDatabase;
+class CSqlDatabaseImpl;
+class RSqlStatement;
+class CSqlStatementImpl;
+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.
+
+The container can contain:
+- security policies that apply to the database.
+- security policies that apply to individual database objects, i.e. database tables.
+
+For the database, you use RSqlSecurityPolicy::SetDbPolicy() to apply a separate
+security policy to:
+- the database schema.
+- read activity on the database.
+- write activity on the database.
+
+For database tables, you use RSqlSecurityPolicy::SetPolicy() to apply a separate
+security policy to:
+- write activity on each named database table.
+- read activity on each named database table.
+
+A client uses a RSqlSecurityPolicy object to create a secure database. It does this by:
+- creating a RSqlSecurityPolicy object.
+- setting all the appropriate security policies into it.
+- passing the object as an argument to RSqlDatabase::Create().
+- closing the RSqlSecurityPolicy object on return from RSqlDatabase::Create().
+
+Once a secure shared database has been created with specific security policies,
+these policies are made persistent and cannot be changed during the life of
+that database.
+
+Security policies are encapsulated by TSecurityPolicy objects.
+The general usage pattern is to create the security policies container object
+(RSqlSecurityPolicy) using a default security policy (TSecurityPolicy), and then
+to assign more specific 'overriding' security policies.
+
+The following code fragment shows how you do this:
+   
+@code
+TSecurityPolicy defaultPolicy;
+RSqlSecurityPolicy securityPolicy;
+RSqlDatabase database;
+TInt err;
+
+// Create security policies container object using a default security policy.
+securityPolicy.Create(defaultPolicy); 
+
+// Set up policy to apply to database schema
+// and assign it
+TSecurityPolicy schemaPolicy;
+...
+err = securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, schemaPolicy);
+
+// Set up policy to apply to write activity on the database
+// and assign it
+TSecurityPolicy writePolicy;
+...
+err = securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, writePolicy);
+
+// Set up policy to apply to write activity to the database table named "Table1"
+// and assign it
+TSecurityPolicy tablePolicy1;
+...
+err = securityPolicy.SetPolicy(RSqlSecurityPolicy::ETable, _L("Table1"), RSqlSecurityPolicy::EWritePolicy, tablePolicy1);
+
+// Set up policy to apply to read activity to the database table named "Table2"
+TSecurityPolicy tablePolicy2;
+err = securityPolicy.SetPolicy(RSqlSecurityPolicy::ETable, _L("Table2"), RSqlSecurityPolicy::EReadPolicy, tablePolicy2);
+
+// Create the database, passing the security policies
+err = database.Create(KDatabaseName, securityPolicy);
+
+// We can close the RSqlSecurityPolicy object.
+securityPolicy.Close();
+@endcode
+
+Note that in this example code fragment, the client has not assigned specific
+overriding policies for all possible cases; for example, no overriding policy
+has been assigned to control read activity on the database, read activity
+on "Table1", nor write activity on "Table2".
+For these cases, the default security policy will apply.
+
+A client can also retrieve a database's security policies by calling
+RSqlDatabase::GetSecurityPolicy(); this returns a RSqlSecurityPolicy object
+containing the security policies. Note that it is the client's responsibility
+to close the RSqlSecurityPolicy object when the client no longer needs it. The
+following code fragment suggests how you might do this:
+
+@code
+RSqlDatabase database;
+RSqlSecurityPolicy securityPolicy;
+
+// Retrieve the security policies; on return from the call to 
+// GetSecurityPolicy(), the RSqlSecurityPolicy object passed 
+// to this function will contain the security policies.
+database.GetSecurityPolicy(securityPolicy);
+...
+// This is the security policy that applies to database schema
+TSecurityPolicy schemaPolicy = securityPolicy.DbPolicy(RSqlSecurityPolicy::ESchemaPolicy);
+...
+// This is the security policy that applies to write activity to the database
+// table named "Table1".
+TSecurityPolicy writePolicy = securityPolicy.Policy(RSqlSecurityPolicy::ETable, _L("Table1"), RSqlSecurityPolicy::EWritePolicy);
+...
+// Close the RSqlSecurityPolicy object when no longer needed.
+securityPolicy.Close();
+@endcode
+
+Note that in the cases where an 'overriding' security policy was not originally assigned,
+then the security policy returned will simply be the default security policy.
+
+@see TSecurityPolicy
+@see RSqlDatabase
+@see RSqlSecurityPolicy::SetDbPolicy()
+@see RSqlSecurityPolicy::SetPolicy()
+
+@publishedAll
+@released
+*/
+class RSqlSecurityPolicy
+	{
+	friend class RSqlDatabase;
+	
+public:
+	/**
+	Defines a set of values that represents the database security policy types.
+	Each database security policy type refers to a set of capabilities encapsulated in 
+	a TSecurityPolicy object. The TSecurityPolicy object defines what capabilities the calling
+	application must have in order to perform partiqular database operation.
+	@see TSecurityPolicy
+	*/
+	enum TPolicyType 
+		{
+		/**
+		Schema database security policy. An application with schema database security policy can 
+		modify the database schema, write to database, read from database.
+		*/
+		ESchemaPolicy, 
+		/**
+		Read database security policy. An application with read database security policy can 
+		read from database.
+		*/
+		EReadPolicy, 
+		/**
+		Write database security policy. An application with write database security policy can 
+		write to database.
+		*/
+		EWritePolicy
+		};
+	/**
+	Not currently supported.
+
+	Defines a set of values that represents the database objects which can be protected by 
+	database security policy types.
+	*/
+	enum TObjectType 
+		{
+		ETable
+		};
+	IMPORT_C RSqlSecurityPolicy();
+	IMPORT_C TInt Create(const TSecurityPolicy& aDefaultPolicy);
+	IMPORT_C void CreateL(const TSecurityPolicy& aDefaultPolicy);
+	IMPORT_C void Close();
+	IMPORT_C TInt SetDbPolicy(TPolicyType aPolicyType, const TSecurityPolicy& aPolicy);
+	IMPORT_C TInt SetPolicy(TObjectType aObjectType, const TDesC& aObjectName, TPolicyType aPolicyType, const TSecurityPolicy& aPolicy);
+	IMPORT_C TSecurityPolicy DefaultPolicy() const;
+	IMPORT_C TSecurityPolicy DbPolicy(TPolicyType aPolicyType) const;
+	IMPORT_C TSecurityPolicy Policy(TObjectType aObjectType, const TDesC& aObjectName, TPolicyType aPolicyType) const;
+	
+	IMPORT_C void ExternalizeL(RWriteStream& aStream) const;
+	IMPORT_C void InternalizeL(RReadStream& aStream);
+		
+private:	
+	void Set(CSqlSecurityPolicy& aImpl);
+	CSqlSecurityPolicy& Impl() const;
+					
+private:
+	CSqlSecurityPolicy* iImpl;
+	};
+	
+/**
+A handle to a SQL database.
+
+A RSqlDatabase object is, in effect, a handle to the SQL database. A client can:
+- create a SQL database by calling RSqlDatabase::Create().
+- open an existing SQL database by calling RSqlDatabase::Open().
+- close a SQL database by calling RSqlDatabase::Close().
+- copy a SQL database by calling RSqlDatabase::Copy().
+- delete a SQL database by calling RSqlDatabase::Delete().
+- 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.
+- a secure database is created if the RSqlDatabase::Create(const TDesC&, const RSqlSecurityPolicy&)
+variant is used. In this case, a container containing a collection of security
+policies needs to be set up first and passed to this Create() function.
+See references to RSqlSecurityPolicy for more information on security policies.
+
+A client can also specify how it wants a transaction to interact with
+other transactions that may be running concurrently. The various ways in which
+transactions can interact (i.e. how one transaction can affect another) are
+referred to as "transaction isolation levels", and are defined by the values
+of the TIsolationLevel enum. A client specifies this by calling RSqlDatabase::SetIsolationLevel().
+
+Each of the various flavours of Open and Create allows the optional provision of a
+configuration string. It is acceptable for this string to be missing.
+In the case where the string is missing, the config in the SqlServer.sql file
+will be used. If that does not exist then the MMH macro definitions will be used.
+
+The config string is in the format PARAM=VALUE; PARAM=VALUE;...
+
+Allowed parameters are:
+	cache_size=nnnn
+	page_size=nnnn
+	encoding=UTF8|UTF16
+
+Badly formed config strings are reported as KErrArgument
+
+The string may not exceed 255 characters.
+
+Please note that a database can only be accessed within the thread where it has been created. It is then not possible
+to create a database from thread1 and access it from thread2.
+
+A client calls RSqlDatabase::Exec() to execute SQL statements.
+@see RSqlDatabase::Create()
+@see RSqlDatabase::Open()
+@see RSqlDatabase::Close()
+@see RSqlDatabase::Copy()
+@see RSqlDatabase::Delete()
+@see RSqlDatabase::Attach()
+@see RSqlDatabase::Detach()
+@see RSqlDatabase::SetIsolationLevel()
+@see RSqlDatabase::Exec()
+@see TIsolationLevel
+@see RSqlSecurityPolicy
+
+@publishedAll
+@released
+*/
+class RSqlDatabase
+	{
+	friend class RSqlStatement;
+	friend class TSqlScalarFullSelectQuery;
+	friend class RSqlBlob;
+	friend class RSqlBlobReadStream;
+	friend class RSqlBlobWriteStream;
+	friend class TSqlResourceProfiler;
+	
+public:
+	/**
+	Defines a set of values that represents the transaction isolation level.
+	
+	A transaction isolation level defines the way in which a transaction
+	interacts with other transactions that may be in progress concurrently.
+	
+	A client sets the transaction isolation level by calling SetIsolationLevel()
+	
+	@see RSqlDatabase::SetIsolationLevel()
+	*/
+	enum TIsolationLevel 
+		{
+		/**
+		A transaction can read uncommitted data, i.e. data that is being changed
+		by another transaction, which is still in progress.
+		
+		This means that
+		- a 'database read' transaction will not block 'database write' transactions
+		being performed by different database connections on the same shared database.
+		- a 'database read' transaction will not be blocked by 'database write'
+		transactions performed by the same database connection.
+		- concurrent 'database write' transactions are prevented.
+		
+		This transaction isolation level can be set at any time during
+		the lifetime of the database.
+		
+		@see TIsolationLevel
+		@see RSqlDatabase::SetIsolationLevel()
+		*/
+		EReadUncommitted, 
+
+		/**
+		Not currently supported.
+		
+		A transaction cannot read uncommitted data. "Dirty reads" are prevented.
+		
+		"Dirty read" is a data inconsistency type which can be described with the following example:
+		- Transaction A updates TableA.Column1 value from 1 to 2;
+		- Transaction B reads TableA.Column1 value;
+		- Transaction A rolls back and restores the original value of TableA.Column1 (1);
+		- Transaction B ends showing that TableA.Column1 value is 2, even though, logically and transactionally, 
+		  this data never really even existed in the database because Transaction A never committed that change 
+		  to the database;
+		
+		@see TIsolationLevel
+		@see RSqlDatabase::SetIsolationLevel()
+		*/
+		EReadCommitted, 
+		
+		/**
+		Not currently supported.
+		
+		A transaction cannot change data that is being read by a different transaction. 
+		"Dirty reads" and "non-repeatable reads" are prevented.
+
+		"Non-repeatable reads" is a data inconsistency type which can be described with the following example:
+		- Transaction A reads TableA.Column1 value which is 1;
+		- Transaction B updates TableA.Column1 value from 1 to 2;
+		- Transaction B commits the chages;
+		- Transaction A reads TableA.Column1 value again. Transaction A has inconsistent data because TableA.Column1 
+		  value now is 2 instead of 1, all within the scope of the same Transaction A;
+		
+		@see TIsolationLevel
+		@see RSqlDatabase::SetIsolationLevel()
+		*/
+		ERepeatableRead, 
+		
+		/**
+		Any number of 'database read' transactions can be performed concurrently
+		by different database connections on the same shared database.
+		
+		Only one 'database write' transaction can be performed at any one time. If a
+		'database write' transaction is in progress, then any attempt to start
+		another 'database read' or 'database write' transaction will be blocked
+		until the first 'database write' transaction has completed.
+		
+		This is the default isolation level, if no isolation level is
+		explicitly set.
+		
+		"Dirty reads", "non-repeatable" reads and "phantom reads" are prevented.
+		
+		"Phantom reads" is a data inconsistency type which can be described with the following example:
+		- Transaction A reads all rows that have Column1 = 1;
+		- Transaction B inserts a new row which has Column1 = 1;
+		- Transaction B commits;
+		- Transaction A updates all rows that have Column1 = 1. This will also update the row that 
+		  Transaction B inserted, because Transaction A must read the data again in order to update it.
+		- Transaction A commits;
+		
+		@see TIsolationLevel
+		@see RSqlDatabase::SetIsolationLevel()
+		*/
+		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();
+	
+	IMPORT_C TInt Create(const TDesC& aDbFileName, const TDesC8* aConfig=NULL);
+	IMPORT_C TInt Create(const TDesC& aDbFileName,
+			const RSqlSecurityPolicy& aSecurityPolicy, const TDesC8* aConfig=NULL);
+	IMPORT_C TInt Open(const TDesC& aDbFileName, const TDesC8* aConfig=NULL);
+	IMPORT_C void CreateL(const TDesC& aDbFileName, const TDesC8* aConfig=NULL);
+	IMPORT_C void CreateL(const TDesC& aDbFileName,
+			const RSqlSecurityPolicy& aSecurityPolicy, const TDesC8* aConfig=NULL);
+	IMPORT_C void OpenL(const TDesC& aDbFileName, const TDesC8* aConfig=NULL);
+	
+	IMPORT_C void Close();
+	
+	IMPORT_C TInt Attach(const TDesC& aDbFileName, const TDesC& aDbName);
+	IMPORT_C TInt Detach(const TDesC& aDbName);
+	
+	IMPORT_C static TInt Copy(const TDesC& aSrcDbFileName, const TDesC& aDestDbFileName);
+	IMPORT_C static TInt Delete(const TDesC& aDbFileName);
+	
+	IMPORT_C TInt GetSecurityPolicy(RSqlSecurityPolicy& aSecurityPolicy) const;
+	IMPORT_C void GetSecurityPolicyL(RSqlSecurityPolicy& aSecurityPolicy) const;
+	
+	IMPORT_C TInt SetIsolationLevel(TIsolationLevel aIsolationLevel);
+	
+	IMPORT_C TInt Exec(const TDesC& aSqlStmt);
+	IMPORT_C TInt Exec(const TDesC8& aSqlStmt);
+	
+	IMPORT_C void Exec(const TDesC& aSqlStmt, TRequestStatus& aStatus);
+	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();
+	IMPORT_C TInt GetReserveAccess();
+	IMPORT_C void ReleaseReserveAccess();
+	
+private:
+	CSqlDatabaseImpl& Impl() const;
+
+private:
+	CSqlDatabaseImpl* iImpl;
+	};
+
+/**
+TSqlScalarFullSelectQuery interface is used for executing SELECT sql queries, which 
+return a single row consisting of a single column value.
+
+Examples.
+
+CASE 1 - retrieving records count of a table:
+@code
+RSqlDatabase db;
+//initialize db object....
+.......
+TSqlScalarFullSelectQuery fullSelectQuery(db);
+TInt recCnt = fullSelectQuery.SelectIntL(_L("SELECT COUNT(*) FROM PersonTbl"));
+@endcode
+
+CASE 2 - retrieving specific column value using a condition in the SELECT statement:
+@code
+RSqlDatabase db;
+//initialize db object....
+.......
+TSqlScalarFullSelectQuery fullSelectQuery(db);
+TInt personId = fullSelectQuery.SelectIntL(_L("SELECT ID FROM PersonTbl WHERE Name = 'John'"));
+@endcode
+
+CASE 3 - retrieving a text column value, the receiving buffer is not big enough:
+@code
+RSqlDatabase db;
+//initialize db object....
+.......
+TSqlScalarFullSelectQuery fullSelectQuery(db);
+HBufC* buf = HBufC::NewLC(20);
+TPtr name = buf->Des();
+TInt rc = fullSelectQuery.SelectTextL(_L("SELECT Name FROM PersonTbl WHERE Id = 1"), name);
+TEST(rc >= 0); //the function may return only non-negative values
+if(rc > 0)
+	{
+	buf = buf->ReAllocL(rc);
+	CleanupStack::Pop();	
+	CleanupStack::PushL(buf);
+	name.Set(buf->Des());
+	rc = fullSelectQuery.SelectTextL(_L("SELECT Name FROM PersonTbl WHERE Id = 1"), name);
+	TEST(rc == 0);
+	}
+CleanupStack::PopAndDestroy();//buf
+@endcode
+
+@see RSqlDatabase
+
+@publishedAll
+@released
+*/
+class TSqlScalarFullSelectQuery
+	{
+public:
+	IMPORT_C TSqlScalarFullSelectQuery();
+	IMPORT_C TSqlScalarFullSelectQuery(RSqlDatabase& aDatabase);
+	IMPORT_C void SetDatabase(RSqlDatabase& aDatabase);
+
+	IMPORT_C TInt SelectIntL(const TDesC& aSqlStmt);
+	IMPORT_C TInt64 SelectInt64L(const TDesC& aSqlStmt);
+	IMPORT_C TReal SelectRealL(const TDesC& aSqlStmt);
+	IMPORT_C TInt SelectTextL(const TDesC& aSqlStmt, TDes& aDest);
+	IMPORT_C TInt SelectBinaryL(const TDesC& aSqlStmt, TDes8& aDest);
+
+	IMPORT_C TInt SelectIntL(const TDesC8& aSqlStmt);
+	IMPORT_C TInt64 SelectInt64L(const TDesC8& aSqlStmt);
+	IMPORT_C TReal SelectRealL(const TDesC8& aSqlStmt);
+	IMPORT_C TInt SelectTextL(const TDesC8& aSqlStmt, TDes& aDest);
+	IMPORT_C TInt SelectBinaryL(const TDesC8& aSqlStmt, TDes8& aDest);
+	
+private:
+	inline CSqlDatabaseImpl& Impl() const;
+	
+private:	
+	CSqlDatabaseImpl* iDatabaseImpl;
+	};
+
+/**
+An enumeration whose values represent the supported database column types.
+
+
+@see RSqlStatement::ColumnType()
+
+@publishedAll
+@released
+*/
+enum TSqlColumnType 
+	{
+	/**
+	Null column value.
+	*/
+	ESqlNull,
+	
+ 	/**
+ 	32-bit integer column value.
+ 	*/  
+	ESqlInt, 
+	
+ 	/**
+ 	64-bit integer column value.
+ 	*/
+	ESqlInt64, 
+	
+	/**
+	64-bit floating point column value.
+	*/
+	ESqlReal, 
+	
+	/**
+	Unicode text, a sequence of 16-bit character codes.
+	*/
+	ESqlText, 
+	
+	/**
+	Binary data, a sequence of bytes.
+	*/
+	ESqlBinary
+	};
+
+/**
+Represents an SQL statement.
+
+An object of this type can be used to execute all types of SQL statements; this
+includes SQL statements with parameters.
+
+If a SELECT statament is passed to RSqlStatement::Prepare(), then the returned record set 
+is forward only, non-updateable.
+
+There are a number of ways that this object is used; here are some examples.
+
+CASE 1 - the execution of a SQL statement, which does not return record set:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("INSERT INTO Tbl1(Fld1) VALUES(:Val)"));
+TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
+for(TInt i=1;i<=10;++i)
+	{
+	err = stmt.BindInt(paramIndex, i);
+	err = stmt.Exec();
+	err = stmt.Reset();
+	}
+stmt.Close();
+@endcode
+
+The following pseudo code shows the general pattern:
+
+@code
+<RSqlStatement::Prepare()>
+[begin:]
+<RSqlStatement::Bind<param_type>()>
+<RSqlStatement::Exec()>
+[<RSqlStatement::Reset()>]
+[<RSqlStatement::Bind<param_type>()>]
+[<Goto :begin>]
+@endcode
+
+CASE 2 - the execution of a SQL statement, which returns a record set:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("SELECT Fld1 FROM Tbl1 WHERE Fld1 > :Val"));
+TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
+err = stmt.BindInt(paramIndex, 5);
+TInt columnIndex = stmt.ColumnIndex(_L("Fld1"));
+while((err = stmt.Next()) == KSqlAtRow)
+	{
+	TInt val = stmt.ColumnInt(columnIndex);
+	RDebug::Print(_L("val=%d\n"), val);
+	}
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+stmt.Close();
+@endcode
+
+The following pseudo code shows the general pattern:
+
+@code
+<RSqlStatement::Prepare()>
+[begin:]
+<while (RSqlStatement::Next() == KSqlAtRow)>
+	<do something with the records>
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+[<RSqlStatement::Reset()>]
+[<RSqlStatement::Bind<param_type>()>]
+[<Goto begin>]
+@endcode
+
+CASE 3.1 - SELECT statements: large column data processing, where the data is
+copied into a buffer supplied by the client:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("SELECT BinaryField FROM Tbl1"));
+TInt columnIndex = stmt.ColumnIndex(_L("BinaryField"));
+while((err = stmt.Next()) == KSqlAtRow)
+	{
+	TInt size = stmt. ColumnSize(columnIndex);
+	HBufC8* buf = HBufC8::NewL(size);
+	err = stmt.ColumnBinary(columnIndex, buf->Ptr());
+	<do something with the data>;
+	delete buf;
+	}
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+stmt.Close();
+@endcode
+
+CASE 3.2 - SELECT statements: large column data processing, where the data is
+accessed by the client without copying:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("SELECT BinaryField FROM Tbl1"));
+TInt columnIndex = stmt.ColumnIndex(_L("BinaryField"));
+while((err = stmt.Next()) == KSqlAtRow)
+	{
+	TPtrC8 data = stmt.ColumnBinaryL(columnIndex);
+	<do something with the data>;
+	}
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+stmt.Close();
+@endcode
+
+CASE 3.3 - SELECT statements, large column data processing (the data is accessed by 
+the client without copying), leaving-safe processing:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("SELECT BinaryField FROM Tbl1"));
+TInt columnIndex = stmt.ColumnIndex(_L("BinaryField"));
+while((err = stmt.Next()) == KSqlAtRow)
+	{
+	TPtrC8 data;
+	TInt err = stmt.ColumnBinary(columnIndex, data);
+	if(err == KErrNone)
+		{
+		<do something with the data>;
+		}
+	}
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+stmt.Close();
+@endcode
+
+CASE 3.4 - SELECT statements: large column data processing, where the data is
+accessed by the client using a stream:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = stmt.Prepare(database, _L("SELECT BinaryField FROM Tbl1"));
+TInt columnIndex = stmt.ColumnIndex(_L("BinaryField"));
+while((err = stmt.Next()) == KSqlAtRow)
+	{
+	RSqlColumnReadStream stream;
+	err = stream.ColumnBinary(stmt, columnIndex);
+	<do something with the data in the stream>;
+	stream.Close();
+	}
+if(err == KSqlAtEnd)
+	<OK - no more records>;
+else
+	<process the error>;
+stmt.Close();
+@endcode
+
+CASE 4 - the execution of a SQL statement with parameter(s), some of which may
+be large text or binary values:
+
+@code
+RSqlDatabase database;
+.........
+RSqlStatement stmt;
+TInt err = 
+	stmt.Prepare(database, _L("UPDATE Tbl1 SET LargeTextField = :LargeTextVal WHERE IdxField = :KeyVal"));
+TInt paramIndex1 = stmt.ParameterIndex(_L(":LargeTextVal"));
+TInt paramIndex2 = stmt.ParameterIndex(_L(":KeyVal"));
+for(TInt i=1;i<=10;++i)
+	{
+	RSqlParamWriteStream stream;
+	err = stream.BindText(stmt, paramIndex1);
+	<insert large text data into the stream>;
+	stream.Close();
+	err = stmt.BindInt(paramIndex2, i);
+	err = stmt.Exec();
+	stmt.Reset();
+	}
+stmt.Close();
+@endcode
+
+The following table shows what is returned when the caller uses a specific
+column data retrieving function on a specific column type.
+
+@code
+--------------------------------------------------------------------------------
+Column type | ColumnInt() ColumnInt64() ColumnReal() ColumnText() ColumnBinary()
+--------------------------------------------------------------------------------
+Null........|.0...........0.............0.0..........KNullDesC....KNullDesC8
+Int.........|.Int.........Int64.........Real.........KNullDesC....KNullDesC8 
+Int64.......|.clamp.......Int64.........Real.........KNullDesC....KNullDesC8 
+Real........|.round.......round.........Real.........KNullDesC....KNullDesC8 
+Text........|.0...........0.............0.0..........Text.........KNullDesC8   
+Binary......|.0...........0.............0.0..........KNullDesC....Binary
+--------------------------------------------------------------------------------
+@endcode
+Note the following definitions:
+- "clamp": return KMinTInt or KMaxTInt if the value is outside the range that can be 
+represented by the type returned by the accessor function.
+- "round": the floating point value will be rounded up to the nearest integer.
+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
+*/
+class RSqlStatement
+	{
+	friend class RSqlColumnReadStream;
+	friend class RSqlParamWriteStream;
+
+public:
+	IMPORT_C RSqlStatement();
+	IMPORT_C TInt Prepare(RSqlDatabase& aDatabase, const TDesC& aSqlStmt);
+	IMPORT_C TInt Prepare(RSqlDatabase& aDatabase, const TDesC8& aSqlStmt);
+	IMPORT_C void PrepareL(RSqlDatabase& aDatabase, const TDesC& aSqlStmt);
+	IMPORT_C void PrepareL(RSqlDatabase& aDatabase, const TDesC8& aSqlStmt);
+	IMPORT_C void Close();
+	IMPORT_C TBool AtRow() const;
+	IMPORT_C TInt Reset();
+	IMPORT_C TInt Exec();
+	IMPORT_C void Exec(TRequestStatus& aStatus);
+	IMPORT_C TInt Next();
+	
+	IMPORT_C TInt ParameterIndex(const TDesC& aParameterName) const;
+	IMPORT_C TInt ColumnCount() const;
+	IMPORT_C TInt ColumnIndex(const TDesC& aColumnName) const;
+	IMPORT_C TSqlColumnType ColumnType(TInt aColumnIndex) const;
+	IMPORT_C TInt DeclaredColumnType(TInt aColumnIndex, TSqlColumnType& aColumnType) const;
+	IMPORT_C TInt ColumnSize(TInt aColumnIndex) const;
+	
+	IMPORT_C TInt BindNull(TInt aParameterIndex);
+	IMPORT_C TInt BindInt(TInt aParameterIndex, TInt aParameterValue);
+	IMPORT_C TInt BindInt64(TInt aParameterIndex, TInt64 aParameterValue);
+	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;
+	IMPORT_C TInt64 ColumnInt64(TInt aColumnIndex) const;
+	IMPORT_C TReal ColumnReal(TInt aColumnIndex) const;
+	
+	IMPORT_C TPtrC ColumnTextL(TInt aColumnIndex) const;
+	IMPORT_C TInt ColumnText(TInt aColumnIndex, TPtrC& aPtr) const;
+	IMPORT_C TInt ColumnText(TInt aColumnIndex, TDes& aDest) const;
+	
+	IMPORT_C TPtrC8 ColumnBinaryL(TInt aColumnIndex) const;
+	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;
+	
+private:
+	CSqlStatementImpl* 	iImpl;
+	
+	};
+
+/**
+The read stream interface.
+
+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.
+
+@code
+RSqlDatabase db;
+<open/create "db" object>;
+RSqlStatement stmt;
+<prepare "stmt" object>;
+TInt rc = stmt.Next();
+if(rc == KSqlAtRow)
+	{
+	RSqlColumnReadStream colStream;
+	CleanupClosePushL(colStream);
+	User::LeaveIfError(colStream.ColumnBinary(stmt, <column_number>));
+	TInt size = stmt.ColumnSize(<column_number>);
+	//read the column data in a buffer ("buf" variable).
+	//(or the column data can be retrieved in a smaller portions)
+	colStream.ReadL(buf, size);
+	//Close the stream
+	CleanupStack::PopAndDestroy(&colStream);
+	}
+else
+	{
+	...
+	}
+@endcode
+
+CASE 2 - processing large text column data.
+
+@code
+RSqlDatabase db;
+<open/create "db" object>;
+RSqlStatement stmt;
+<prepare "stmt" object>;
+TInt rc = stmt.Next();
+if(rc == KSqlAtRow)
+	{
+	RSqlColumnReadStream colStream;
+	CleanupClosePushL(colStream);
+	User::LeaveIfError(colStream.ColumnText(stmt, <column_number>));
+	TInt size = stmt.ColumnSize(<column_number>);
+	//read the column data in a buffer ("buf" variable).
+	//(or the column data can be retrieved in a smaller portions)
+	colStream.ReadL(buf, size);
+	//Close the stream
+	CleanupStack::PopAndDestroy(&colStream);
+	}
+else
+	{
+	...
+	}
+@endcode
+
+@see RSqlBlobReadStream
+@see TSqlBlob
+
+@publishedAll
+@released
+*/
+class RSqlColumnReadStream : public RReadStream
+	{
+public:	
+	IMPORT_C TInt ColumnText(RSqlStatement& aStmt, TInt aColumnIndex);
+	IMPORT_C TInt ColumnBinary(RSqlStatement& aStmt, TInt aColumnIndex);
+	IMPORT_C void ColumnTextL(RSqlStatement& aStmt, TInt aColumnIndex);
+	IMPORT_C void ColumnBinaryL(RSqlStatement& aStmt, TInt aColumnIndex);
+
+	};
+
+/**
+The write stream interface.
+
+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.
+
+@code
+RSqlDatabase db;
+<open/create "db" object>;
+RSqlStatement stmt;
+<prepare "stmt" object>;//The SQL statement references large binary parameter
+RSqlParamWriteStream paramStream;
+CleanupClosePushL(paramStream);
+User::LeaveIfError(paramStream.BindBinary(stmt, <parameter_number>));
+//Write out the parameter data
+paramStream.WriteL(..);
+paramStream << <data>;
+...
+//Commit the stream
+paramStream.CommitL();
+//Continue with the statement processing issuing Next() or Exec().
+TInt rc = stmt.Next();//rc = stmt.Exec()
+//Close the stream
+CleanupStack::PopAndDestroy(&paramStream);
+@endcode
+
+CASE 2 - binding a large text parameter.
+
+@code
+RSqlDatabase db;
+<open/create "db" object>;
+RSqlStatement stmt;
+<prepare "stmt" object>;//The SQL statement references large text parameter
+RSqlParamWriteStream paramStream;
+CleanupClosePushL(paramStream);
+User::LeaveIfError(paramStream.BindText(stmt, <parameter_number>));
+//Write out the parameter data
+paramStream.WriteL(..);
+paramStream << <data>;
+...
+//Commit the stream
+paramStream.CommitL();
+//Continue with the statement processing issuing Next() or Exec().
+TInt rc = stmt.Next();//rc = stmt.Exec()
+//Close the stream
+CleanupStack::PopAndDestroy(&paramStream);
+@endcode
+
+@see RSqlBlobWriteStream
+@see TSqlBlob
+
+@publishedAll
+@released
+*/
+class RSqlParamWriteStream : public RWriteStream
+	{
+public:	
+	IMPORT_C TInt BindText(RSqlStatement& aStmt, TInt aParameterIndex);
+	IMPORT_C TInt BindBinary(RSqlStatement& aStmt, TInt aParameterIndex);
+	IMPORT_C void BindTextL(RSqlStatement& aStmt, TInt aParameterIndex);
+	IMPORT_C void BindBinaryL(RSqlStatement& aStmt, TInt aParameterIndex);
+
+	};
+
+/**
+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.
+
+@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 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)
+	{
+	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);				  
+	};
+
+/**
+Defines a set of categories for the values returned by the SQL API.
+
+A call to an SQL API may complete with a non-zero return code indicating that some
+unexpected behaviour has occurred. This can be categorised in a number of ways,
+for example, as a Symbian OS error, or as a database error etc. 
+
+Callers to the SQL API may not want to be concerned with the detailed meaning of
+a specific return code value, and may find it sufficient just to know the category
+of the error.
+
+The category associated with a specific return code can be found by passing the 
+return code value to the function SqlRetCodeClass().
+
+@publishedAll
+@released
+*/
+enum TSqlRetCodeClass 
+	{
+	/**
+	Indicates that a return code is just for information.
+	
+	This category corresponds to the SQL API return codes: KSqlAtRow and KSqlAtEnd. 
+	
+	@see SqlRetCodeClass()
+	@see TSqlRetCodeClass
+	@see KSqlAtRow 
+	@see KSqlAtEnd
+	*/
+	ESqlInformation, 
+	
+	/**
+	Indicates that a return code represents a database-specific error.
+	
+	This category corresponds to SQL API return codes in the range KSqlErrGeneral to KSqlErrStmtExpired.
+	
+	@see SqlRetCodeClass()
+	@see TSqlRetCodeClass
+	@see KSqlErrGeneral
+	@see KSqlErrStmtExpired
+	*/
+	ESqlDbError,
+	
+	/**
+	Indicates that a return code represents a Symbian OS error.
+	
+	This category corresponds to SQL API return codes in the range KErrPermissionDenied to KErrNone,
+	
+	@see SqlRetCodeClass()
+	@see TSqlRetCodeClass
+	@see KErrPermissionDenied
+	@see KErrNone
+	*/
+	ESqlOsError 
+	};
+
+/**
+An information type return code from a call to RSqlStatement::Next().
+
+It means that the RSqlStatement object points to a valid row, and that
+the user can access the column data using the appropriate RSqlStatement
+member functions.
+
+@see RSqlStatement::Next()
+@see RSqlStatement
+@see ESqlInformation
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlAtRow = 1;
+
+/**
+An information type return code from a call to RSqlStatement::Next().
+
+It means that the RSqlStatement object does not point to a valid row,
+and that column data accessors cannot be used.
+
+@see RSqlStatement::Next()
+@see RSqlStatement
+@see ESqlInformation
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlAtEnd = 2;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates a general SQL error or a missing database.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrGeneral		= -311;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates an internal logic error in the SQL database engine, and specifically
+that an internal consistency check within the SQL database engine has failed.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrInternal		= -312;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that access permission has been denied.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrPermission	= -313;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates an internal logic error in the SQL database engine, and specifically
+that a callback routine requested an abort.
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrAbort			= -314;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that the database file is locked.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrBusy			= -315;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that a table in the database is locked.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrLocked		= -316;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates an attempt to write to a database that is read-only.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrReadOnly		= -318;
+
+/**
+SQL database-specific error type. Operation terminated.
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrInterrupt		= -319;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that a disk I/O error has occurred.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrIO			= -320;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that the database disk image is malformed.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrCorrupt		= -321;
+
+/**
+SQL database-specific error type. Table or record not found.
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrNotFound		= -322;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that an insertion operation has failed because an autoincrement column used up 
+all awailable rowids.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrFull			= -323;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates a failure to open the database file.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrCantOpen		= -324;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates a database lock protocol error.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrProtocol		= -325;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that the database is empty.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrEmpty			= -326;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that a prepared SQL statement is no longer valid 
+and cannot be executed.
+
+The most common reason for this return code is that the database schema was modified after
+the SQL statement was prepared. The SQL statement must be prepared again
+using the RSqlStatement::Prepare() member functions.
+
+Another possible reason for this return code is a detached database.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrSchema		= -327;
+
+/**
+SQL database-specific error type. Too much data for one row.
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrTooBig		= -328;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates an abort due to constraint violation.
+
+"Constraint violation" means violation of one or more column constraints ("NOT NULL", "PRIMARY KEY",
+"UNIQUE", "CHECK", "DEFAULT", "COLLATE" SQL keywords) or table constraints ("PRIMARY KEY", "UNIQUE", 
+"CHECK" SQL keywords).
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrConstraint	= -329;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates a data type mismatch.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrMismatch		= -330;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates an internal logic error in the SQL database engine.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrMisuse		= -331;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that a parameter index value is out of range.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrRange			= -335;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that the file that has been opened is not a database file.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrNotDb			= -336;
+
+/**
+An SQL database-specific error type return code from a call to the SQL API.
+
+It indicates that an SQL statement has expired, and needs to be prepared again.
+
+@see RSqlStatement
+@see ESqlDbError
+@see TSqlRetCodeClass
+
+@publishedAll
+@released
+*/
+const TInt KSqlErrStmtExpired	= -360;
+
+IMPORT_C TSqlRetCodeClass SqlRetCodeClass(TInt aSqlRetCode);
+
+#endif //__SQLDB_H__