epoc32/include/sqldb.h
branchSymbian2
changeset 2 2fe1408b6811
parent 0 061f57f2323e
child 4 837f303aceeb
--- a/epoc32/include/sqldb.h	Tue Nov 24 13:55:44 2009 +0000
+++ b/epoc32/include/sqldb.h	Tue Mar 16 16:12:26 2010 +0000
@@ -1,1 +1,1395 @@
-sqldb.h
+// 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
+// which accompanies this distribution, and is available
+// at the URL "http://www.symbianfoundation.org/legal/licencesv10.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
+
+//Forward declarations
+class CSqlSecurityPolicy;
+class RSqlDatabase;
+class CSqlDatabaseImpl;
+class RSqlStatement;
+class CSqlStatementImpl;
+class RSqlColumnReadStream;
+class RSqlParamWriteStream;
+class TSqlScalarFullSelectQuery;
+
+/**
+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().
+
+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;
+	
+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
+		};
+		
+	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 TBool InTransaction() const;
+	IMPORT_C TInt Size() const;
+	
+	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.
+
+@see KMinTInt
+@see KMaxTInt
+@see KNullDesC
+@see KNullDesC8
+
+@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 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;
+	
+private:
+	CSqlStatementImpl& Impl() const;
+	
+private:
+	CSqlStatementImpl* 	iImpl;
+	
+	};
+
+/**
+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 derives from RReadStream, which means that all RReadStream public
+member functions and predefined stream operators \>\> can be used to deal
+with column data.
+
+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
+
+@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 a large amount of either 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.
+
+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
+
+@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);
+
+	};
+
+/**
+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.
+
+@internalAll
+@released
+*/
+class TSqlResourceTester
+	{
+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);
+
+	};
+
+/**
+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__