persistentstorage/sql/SRC/Client/SqlStatementImpl.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Client/SqlStatementImpl.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,872 @@
+// 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:
+//
+
+#include "SqlStatementImpl.h" 	//CSqlStatementImpl
+#include "SqlDatabaseImpl.h"	//CSqlDatabaseImpl::Session()
+
+//Constants
+
+_LIT(KSemiColon,";");
+
+_LIT(KTextKWD, 	"TEXT");
+_LIT(KCharKWD, 	"CHAR");
+_LIT(KClobKWD, 	"CLOB");
+
+_LIT(KBinaryKWD,"BINARY");
+_LIT(KBlobKWD,	"BLOB");
+
+_LIT(KRealKWD, 	"REAL");
+_LIT(KFloatKWD, "FLOAT");
+_LIT(KDoubleKWD,"DOUBLE");
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////             RSqlLongColumnColl        ////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+This "comparison" function is used for searching a particular column value, identified by aIndex, in the long column 
+values collection.
+@param aIndex An integer pointer to long column index value
+@param aData A reference to particular elemt of the long column values collection
+@return True of the index of aData item is the same as *aIndex, false otherwise
+@panic SqlDb 4 In _DEBUG mode, aIndex is NULL.
+@panic SqlDb 4 In _DEBUG mode, *aIndex value is negative.
+*/
+TBool RSqlLongColumnColl::TData::Compare(const TInt* aIndex, const RSqlLongColumnColl::TData& aData)
+	{
+	__SQLASSERT(aIndex != NULL, ESqlPanicBadArgument);
+	__SQLASSERT(*aIndex >= 0, ESqlPanicBadArgument);
+	return *aIndex == aData.iIndex;
+	}
+
+/**
+Reads a long column value, identified by aColumnIndex parameter, from the server and stores the value in the collection.
+@param aReader A RSqlLongColumnColl::TColumnReader object, which performs the "read column value" operation.
+@param aColumnIndex Column index
+@param aColumnSize The column size in bytes
+@panic SqlDb 4 In _DEBUG mode, aColumnIndex value is negative.
+@panic SqlDb 4 In _DEBUG mode, aColumnSize is less than KSqlMaxDesLen (not a long column value)
+@return KErrNone The call has completed successfully;
+		KErrNoMemory Out of memory;
+        Note that other system-wide or database specific error codes may also be returned.
+*/
+TInt RSqlLongColumnColl::Append(RSqlLongColumnColl::TColumnReader& aReader, TInt aColumnIndex, TInt aColumnSize)
+	{
+	__SQLASSERT(aColumnIndex >= 0, ESqlPanicBadArgument);
+	__SQLASSERT(aColumnSize >= KSqlMaxDesLen, ESqlPanicBadArgument);
+	LONGCOL_INVARIANT();
+	HBufC8* colBuf = HBufC8::New(aColumnSize);
+	if(!colBuf)
+		{
+		return KErrNoMemory;	
+		}
+	TPtr8 ptr = colBuf->Des();
+	TInt err = aReader.Read(aColumnIndex, ptr);
+	if(err == KErrNone)
+		{
+		err = iValues.Append(RSqlLongColumnColl::TData(aColumnIndex, colBuf));	
+		}
+	if(err != KErrNone)
+		{
+		delete colBuf;	
+		}
+	LONGCOL_INVARIANT();
+	return err;
+	}
+	
+#ifdef _DEBUG
+/**
+RSqlLongColumnColl invariant.
+The collection cannot have two column values with the same column index.
+The collection cannot have NULL column value, or negative column index.
+*/
+void RSqlLongColumnColl::Invariant() const
+	{
+	for(TInt i=iValues.Count()-1;i>=0;--i)
+		{
+		const RSqlLongColumnColl::TData& data = iValues[i];
+		__SQLASSERT(data.iIndex >= 0, ESqlPanicInternalError);
+		__SQLASSERT(data.iData != NULL, ESqlPanicInternalError);
+		for(TInt j=i-1;j>=0;--j)
+			{
+			__SQLASSERT(data.iIndex != iValues[j].iIndex, ESqlPanicInternalError);
+			}
+		}
+	}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////           CSqlStatementImpl           ////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+RSqlLongColumnColl::TColumnReader derived class, which implements the pure virtual RSqlLongColumnColl::TColumnReader::Read().
+The class is used for retrieving long column values from the server.
+@internalComponent
+*/
+NONSHARABLE_STRUCT(TSqlLongColumnReader) : public RSqlLongColumnColl::TColumnReader
+	{
+	TSqlLongColumnReader(RSqlStatementSession& aStmtSession) :
+		iStmtSession(aStmtSession)
+		{
+		}
+	virtual TInt Read(TInt aColumnIndex, TDes8& aBuf)
+		{
+		return iStmtSession.ReadColumnValue(aColumnIndex, aBuf);
+		}
+	RSqlStatementSession	iStmtSession;
+	};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////           CSqlStatementImpl           ////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Frees the allocated memory and other resources.
+*/
+CSqlStatementImpl::~CSqlStatementImpl()
+	{
+	iDeclaredColumnTypes.Close();
+	iLongColumnColl.Close();
+	iParamValueBuf.Close();
+	iParamNameBuf.Close();
+	iColumnValueBuf.Close();
+	iColumnNameBuf.Close();
+	iSqlStmtSession.Close();
+	}
+
+
+
+/**
+Resets the prepared SQL statement back to its initial state and makes it ready for re-execution.
+The parameters of the SQL statement retain their values.
+If CSqlStatementImpl object processes parametrized SQL statement, the parameter values can be bound after 
+the Reset() call.
+
+The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
+cannot be used until the next successful Next() call.
+
+@return KSqlErrStmtExpired, statement expired (if new functions or collating sequences are 
+							registered or if an authorizer function is added or changed);
+		KErrNone, the operation has completed successfully.
+
+@see RSqlStatement::Reset()
+*/
+TInt CSqlStatementImpl::Reset()
+	{
+	iState = CSqlStatementImpl::EUnknown;
+	iLongColumnColl.Reset();
+	if(iParamCnt > 0)
+		{
+		iParamValueBuf.ResetAndMinimize();
+		}
+	return iSqlStmtSession.Reset();
+	}
+
+/**
+Executes the prepared DDL/DML SQL statement. 
+
+If the SQL statement contains parameters, their values will be bound right before the execution.
+
+The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
+cannot be used until the next successful Next() call.
+
+@return >=0, The operation has completed successfully. The number of database rows that were 
+			 changed/inserted/deleted by the most recently completed DDL/DML sql statement.
+			 Exception: If the executed statement is "DELETE FROM <table>", then the function returns 0 
+			 if the operation has completed successfully (disregarding the number of the deleted rows);
+	    KSqlErrStmtExpired, statement has expired (if new functions or collating sequences are 
+							registered or if an authorizer function is added or changed);
+		KErrNoMemory, an out of memory condition has occurred.
+                      Note that database specific errors categorised as ESqlDbError, and
+                      other system-wide error codes may also be returned.
+
+@see RSqlStatement::Exec()
+*/
+TInt CSqlStatementImpl::Exec()
+	{
+	iState = CSqlStatementImpl::EUnknown;
+	TInt rc = 0;
+	if(iBound)
+		{
+		rc = iSqlStmtSession.Exec();	
+		}
+	else
+		{
+		rc = iSqlStmtSession.BindExec(iParamValueBuf);
+		iBound = ETrue;
+		iParamValueBuf.ResetAndMinimize();
+		}
+	return rc;
+	}
+
+/**
+Executes the prepared DDL/DML SQL statement asynchronously. 
+
+If the SQL statement contains parameters, their values will be bound right before the execution.
+
+The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
+cannot be used until the next successful Next() call.
+
+@param aStatus Completion status of asynchronous request, one of the following:
+		 >=0, The operation has completed successfully. The number of database rows that were 
+		   	   changed/inserted/deleted by the most recently completed DDL/DML sql statement.
+			 Exception: If the executed statement is "DELETE FROM <table>", then the function returns 0 
+			 if the operation has completed successfully (disregarding the number of the deleted rows);
+         KSqlErrStmtExpired, the SQL statement has expired (if new functions or
+                            collating sequences have been registered or if an
+                            authorizer function has been added or changed);
+         KErrNoMemory, an out of memory condition has occurred - the statement
+                      will be reset.
+                      Note that aStatus may be set with database specific errors categorised as ESqlDbError, 
+                      and other system-wide error codes.
+
+
+@see RSqlStatement::Exec()
+*/
+void CSqlStatementImpl::Exec(TRequestStatus& aStatus)
+	{
+	iState = CSqlStatementImpl::EUnknown;
+	if(iBound)
+		{
+		iSqlStmtSession.Exec(aStatus);
+		}
+	else
+		{
+		iSqlStmtSession.BindExec(iParamValueBuf, aStatus);
+		iBound = ETrue;
+		//Here: it is not possible to reset iParamValueBuf for "safety", because this is an asynchronous call
+		//      and the buffer content has to be preserved until the operation completes.
+		}
+	}
+
+/**
+Retrieves a record.
+
+If the prepared SQL statement is a "SELECT" statement, and is expected to
+return a set of records, then this function can be used to retrieve that record data.
+
+If the SQL statement contains parameters, then their values must be bound before
+this function is called.
+
+If the call to this function completes successfully, i.e. it returns
+with KSqlAtRow, then this CSqlStatementImpl object contains the record data, and 
+this data will remain valid for access until another call is made to any
+CSqlStatementImpl function.
+
+The record data can be accessed using the following functions:
+- CSqlStatementImpl::ColumnType()
+- CSqlStatementImpl::ColumnSize()
+- CSqlStatementImpl::Column<Type>()
+
+@return KSqlAtRow,      the record data is ready for processing by the caller;
+        KSqlAtEnd,      there is no more record data;
+        KSqlErrBusy,    the database file is locked;
+        KErrNoMemory,   an out of memory condition has occurred - the statement
+                        will be reset;
+        KSqlErrGeneral, a run-time error has occured - this function must not
+                        be called again;        
+        KSqlErrMisuse,  this function has been called after a previous call
+                        returned KSqlAtEnd or KSqlErrGeneral.
+        KSqlErrStmtExpired, the SQL statement has expired (if new functions or
+                            collating sequences have been registered or if an
+                            authorizer function has been added or changed);
+
+@see RSqlStatement::Next()
+*/
+TInt CSqlStatementImpl::Next()
+	{
+	iLongColumnColl.Reset();
+	iColumnValueBuf.ResetAndMinimize();
+	iState = CSqlStatementImpl::EUnknown;
+	TInt err = KErrNone;
+	if(iBound)
+		{
+		err = iSqlStmtSession.Next(iColumnValueBuf);
+		}
+	else
+		{
+		err = iSqlStmtSession.BindNext(iParamValueBuf, iColumnValueBuf);
+		iBound = ETrue;
+		iParamValueBuf.ResetAndMinimize();
+		}
+	iColumnValBufIt.Set(iColumnValueBuf);
+	if(err == KSqlAtRow)
+		{
+		iState = CSqlStatementImpl::EAtRow;
+		}
+	return err;
+	}
+
+/**
+Implements RSqlStatement::BindNull().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindNull()
+*/	
+TInt CSqlStatementImpl::BindNull(TInt aParamIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	iParamValBufIt.SetNull();
+	return KErrNone;
+	}
+	
+/**
+Implements RSqlStatement::BindInt().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindInt()
+*/	
+TInt CSqlStatementImpl::BindInt(TInt aParamIndex, TInt aParamValue)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetInt(aParamValue);
+	}
+	
+/**
+Implements RSqlStatement::BindInt64().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindInt64()
+*/	
+TInt CSqlStatementImpl::BindInt64(TInt aParamIndex, TInt64 aParamValue)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetInt64(aParamValue);
+	}
+	
+/**
+Implements RSqlStatement::BindReal().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindReal()
+*/	
+TInt CSqlStatementImpl::BindReal(TInt aParamIndex, TReal aParamValue)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetReal(aParamValue);
+	}
+	
+/**
+Implements RSqlStatement::BindText().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindText()
+*/	
+TInt CSqlStatementImpl::BindText(TInt aParamIndex, const TDesC& aParamText)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetText(aParamText);
+	}
+	
+/**
+Implements RSqlStatement::BindBinary().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindBinary()
+*/	
+TInt CSqlStatementImpl::BindBinary(TInt aParamIndex, const TDesC8& aParamData)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetBinary(aParamData);
+	}
+
+/**
+Implements RSqlStatement::BindZeroBlob().
+
+@panic SqlDb 5 Parameter index out of bounds.
+
+@see RSqlStatement::BindZeroBlob()
+*/	
+TInt CSqlStatementImpl::BindZeroBlob(TInt aParamIndex, TInt aBlobSize)
+	{
+	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
+	iBound = EFalse;
+	iParamValBufIt.MoveTo(aParamIndex);
+	return iParamValBufIt.SetZeroBlob(aBlobSize);
+	}
+
+/**
+Implements RSqlStatement::ColumnType().
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row.
+
+@see RSqlStatement::ColumnType().
+*/	
+TSqlColumnType CSqlStatementImpl::ColumnType(TInt aColumnIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	return static_cast <TSqlColumnType> (iColumnValBufIt.Type());
+	}
+
+/**
+Implements RSqlStatement::DeclaredColumnType().
+
+@param aColumnIndex The index value identifying the column. This is 0 for the first column.
+@param aColumnType	Output parameter. Upon completion this will contain the type of the column.
+
+@return KErrNone, the operation completed successfully;
+        KErrNoMemory, an out of memory condition has occurred.
+                  One of the other system-wide error codes may also be returned.
+
+@panic SqlDb 5 Column index out of bounds.
+
+@see RSqlStatement::DeclaredColumnType().
+*/
+TInt CSqlStatementImpl::DeclaredColumnType(TInt aColumnIndex, TSqlColumnType& aColumnType)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	if(iDeclaredColumnTypes.Count() == 0 && iColumnCnt > 0) //initialise iDeclaredColumnTypes array if necessary
+		{
+		TInt err = iDeclaredColumnTypes.Reserve(iColumnCnt);//We know what the array size should be - iColumnCnt
+		if(err != KErrNone)
+			{
+			return err;
+			}
+		HBufC* colTypeNamesBuf = NULL;//Buffer for declared column type names, delimited by ';'.
+		TRAP(err, colTypeNamesBuf = GetDeclColumnTypesL());
+		if(err != KErrNone)
+			{
+			__SQLASSERT(!colTypeNamesBuf, ESqlPanicInternalError);
+			iDeclaredColumnTypes.Reset();
+			return err;	
+			}
+		//Iterate over the column type names and map each column type name to one of the TSqlColumnType enum item values.
+		//No error can occur from here till the end of the function code.
+		__SQLASSERT(colTypeNamesBuf != NULL, ESqlPanicInternalError);
+		TPtrC colTypeNames(*colTypeNamesBuf);
+		TInt colIdx = 0;
+		while(colTypeNames.Length() > 0)
+			{
+			TInt pos = colTypeNames.Find(KSemiColon);
+			if(pos < 0)
+				{
+				break;
+				}
+			TPtrC colTypeName(colTypeNames.Ptr(), pos);
+			if(pos == colTypeNames.Length() - 1)
+				{
+				colTypeNames.Set(NULL, 0);	
+				}
+			else
+				{
+				colTypeNames.Set(colTypeNames.Ptr() + pos + 1, colTypeNames.Length() - (pos + 1));
+				}
+			TSqlColumnType colType = ESqlInt;
+			if(colTypeName.FindF(KCharKWD) >= 0 || colTypeName.FindF(KTextKWD) >= 0 || colTypeName.FindF(KClobKWD) >= 0)
+				{
+				colType = ESqlText;
+				}
+			else if(colTypeName.FindF(KBinaryKWD) >= 0 || colTypeName.FindF(KBlobKWD) >= 0)
+				{
+				colType = ESqlBinary;
+				}
+			else if(colTypeName.FindF(KRealKWD) >= 0 || colTypeName.FindF(KFloatKWD) >= 0 || colTypeName.FindF(KDoubleKWD) >= 0)
+				{
+				colType = ESqlReal;
+				}
+			err = iDeclaredColumnTypes.Append(colType);
+			__SQLASSERT(err == KErrNone, ESqlPanicInternalError);//memory for the array elements has been reserved already
+			++colIdx;
+			}//end of - while(colTypeNames.Length() > 0)
+		__SQLASSERT(colIdx == iColumnCnt, ESqlPanicInternalError);
+		delete colTypeNamesBuf;
+		}//end of - if(iDeclaredColumnTypes.Count() == 0 && iColumnCnt > 0)
+	aColumnType = iDeclaredColumnTypes[aColumnIndex];
+	return KErrNone;
+	}
+	
+/**
+Implements RSqlStatement::ColumnSize().
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+
+@see RSqlStatement::ColumnSize().
+*/	
+TInt CSqlStatementImpl::ColumnSize(TInt aColumnIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	return iColumnValBufIt.Size();
+	}
+
+/**
+Implements RSqlStatement::ColumnInt().
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+
+@see RSqlStatement::ColumnInt().
+*/	
+TInt CSqlStatementImpl::ColumnInt(TInt aColumnIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
+	return iColumnValBufIt.Int();
+	}
+	
+/**
+Implements RSqlStatement::ColumnInt64().
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+
+@see RSqlStatement::ColumnInt64().
+*/	
+TInt64 CSqlStatementImpl::ColumnInt64(TInt aColumnIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
+	return iColumnValBufIt.Int64();
+	}
+	
+/**
+Implements RSqlStatement::ColumnReal().
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+
+@see RSqlStatement::ColumnReal().
+*/	
+TReal CSqlStatementImpl::ColumnReal(TInt aColumnIndex)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
+	return iColumnValBufIt.Real();
+	}
+
+/**
+Return a text (16 bit) descriptor to a text column identified by aColumnIndex.
+
+@param aColumnIndex Column index
+@param aPtr An output parameter which will be set to point to the column data.
+
+@return KErrNone, if the function completes successfully,
+                  otherwise one of the other system-wide error codes.
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+*/	
+TInt CSqlStatementImpl::ColumnText(TInt aColumnIndex, TPtrC& aPtr)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	if(iColumnValBufIt.IsPresent())
+		{
+		aPtr.Set(iColumnValBufIt.Text());
+		return KErrNone;
+		}
+	//The text column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
+	//In this case an additional call to the server is made to get the column value.
+	//The column value is stored in a separate collection (iLongColumnColl), because if iColumnValueBuf gets reallocated,
+	//the client can get a dangling pointer to some of the located in iColumnValueBuf text/binary column values.
+	if(iColumnValBufIt.Type() != ESqlText)
+		{
+		aPtr.Set(KNullDesC);
+		return KErrNone;
+		}
+	if(!iLongColumnColl.IsPresent(aColumnIndex))
+		{
+		TSqlLongColumnReader colReader(iSqlStmtSession);
+		TInt err = iLongColumnColl.Append(colReader, aColumnIndex, iColumnValBufIt.Size() * sizeof(TUint16));
+		if(err != KErrNone)
+			{
+			return err;	
+			}
+		}
+	aPtr.Set(iLongColumnColl.Text(aColumnIndex));
+	return KErrNone;
+	}
+
+/**
+Copies the content of a text column, identified by aColumnIndex, to the place refered by aDest parameter.
+
+If the destination buffer is not big enough, the function will copy as much data as possible and will
+return KErrOverflow.
+
+@param aColumnIndex Column index
+@param aDest Refers to the place where the column data will be copied.
+
+@return KErrNone, if the function completes successfully,
+                  otherwise one of the other system-wide error codes.
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+*/	
+TInt CSqlStatementImpl::ColumnText(TInt aColumnIndex, TDes& aDest)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	TInt err = KErrNone;
+	//The text column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
+	//In this case an additional call to the server is made to get the column value.
+	if(!iColumnValBufIt.IsPresent())
+		{
+		if(iColumnValBufIt.Type() != ESqlText)
+			{
+			aDest.Zero();
+			return err;
+			}
+		TPtr8 ptr(reinterpret_cast <TUint8*> (const_cast <TUint16*> (aDest.Ptr())), aDest.MaxLength() * sizeof(TUint16));
+		err = iSqlStmtSession.ReadColumnValue(aColumnIndex, ptr);
+		if(err == KErrNone || err == KErrOverflow)
+			{
+			aDest.SetLength(ptr.Length() / sizeof(TUint16));
+			}
+		}
+	else
+		{
+		TPtrC src = iColumnValBufIt.Text();
+		TInt len = src.Length();
+		if(len > aDest.MaxLength())
+			{
+			len = aDest.MaxLength();
+			err = KErrOverflow;
+			}
+		aDest.Copy(src.Ptr(), len);
+		}
+	return err;
+	}
+
+/**
+Return a binary (8 bit) descriptor to a binary column identified by aColumnIndex.
+
+@param aColumnIndex Column index
+@param aPtr An output parameter which will be set to point to the column data.
+
+@return KErrNone, if the function completes successfully,
+                  otherwise one of the other system-wide error codes.
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+*/	
+TInt CSqlStatementImpl::ColumnBinary(TInt aColumnIndex, TPtrC8& aPtr)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	if(iColumnValBufIt.IsPresent())
+		{
+		aPtr.Set(iColumnValBufIt.Binary());
+		return KErrNone;
+		}
+	//The binary column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
+	//In this case an additional call to the server is made to get the column value.
+	//The column value is stored in a separate collection (iLongColumnColl), because if iColumnValueBuf gets reallocated,
+	//the client can get a dangling pointer to some of the located in iColumnValueBuf text/binary column values.
+	if(iColumnValBufIt.Type() != ESqlBinary)
+		{
+		aPtr.Set(KNullDesC8);
+		return KErrNone;
+		}
+	if(!iLongColumnColl.IsPresent(aColumnIndex))
+		{
+		TSqlLongColumnReader colReader(iSqlStmtSession);
+		TInt err = iLongColumnColl.Append(colReader, aColumnIndex, iColumnValBufIt.Size());
+		if(err != KErrNone)
+			{
+			return err;	
+			}
+		}
+	aPtr.Set(iLongColumnColl.Binary(aColumnIndex));
+	return KErrNone;
+	}
+
+/**
+Copies the content of a binary column, identified by aColumnIndex, to the place refered by aDest parameter.
+
+If the destination buffer is not big enough, the function will copy as much data as possible and will
+return KErrOverflow.
+
+@param aColumnIndex Column index
+@param aDest Refers to the place where the column data will be copied.
+
+@return KErrNone, if the function completes successfully,
+                  otherwise one of the other system-wide error codes.
+
+@panic SqlDb 5 Column index out of bounds.
+@panic SqlDb 11 Statement cursor not positioned on a row
+*/	
+TInt CSqlStatementImpl::ColumnBinary(TInt aColumnIndex, TDes8& aDest)
+	{
+	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
+	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
+	iColumnValBufIt.MoveTo(aColumnIndex);		
+	TInt err = KErrNone;
+	//The binary column value has not been transferred to the client side if its length is >= KSqlMaxDesLen bytes.
+	//In this case an additional call to the server is made to get the column value.
+	if(!iColumnValBufIt.IsPresent())
+		{
+		if(iColumnValBufIt.Type() != ESqlBinary)
+			{
+			aDest.Zero();
+			return err;
+			}
+		err = iSqlStmtSession.ReadColumnValue(aColumnIndex, aDest);
+		}
+	else
+		{
+		TPtrC8 src = iColumnValBufIt.Binary();
+		TInt len = src.Length();
+		if(len > aDest.MaxLength())
+			{
+			len = aDest.MaxLength();
+			err = KErrOverflow;
+			}
+		aDest.Copy(src.Ptr(), len);
+		}
+	return err;
+	}
+
+/**
+ * Obtain the name of a column after performing a query.
+ * 
+ * @param aColumnIndex Column index
+ * @param aNameDest Descriptor which will be set to column name
+ * @return KErrNone if successfull or one of the system-wide error codes on error
+ */
+TInt CSqlStatementImpl::ColumnName(TInt aColumnIndex, TPtrC& aNameDest)
+	{
+	return Index2Name(aColumnIndex, iColumnNameBuf, iColumnCnt, ESqlSrvStmtColumnNames, iColumnNameBufPresent, aNameDest);
+	}
+
+/**
+ * Obtain the name of a parameter after preparing a DML query.
+ * 
+ * @param aParamIndex Parameter index
+ * @param aNameDest Descriptor which will be set to column name
+ * @return KErrNone if successfull or one of the system-wide error codes on error
+ */
+TInt CSqlStatementImpl::ParameterName(TInt aParamIndex, TPtrC& aNameDest)
+	{
+	return Index2Name(aParamIndex, iParamNameBuf, iParamCnt, ESqlSrvStmtParamNames, iParamNameBufPresent, aNameDest);
+	}
+
+
+TInt CSqlStatementImpl::Name2Index(const TDesC& aName, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent)
+	{
+	if(aCount == 0)
+		{
+		return KErrNotFound;	
+		}
+	TInt err = CheckNameBufPresent(aPresent, aNameBufFlat, aCount, aFunction);
+	if ( err != KErrNone ) 
+		{
+		return err;
+		}
+	TInt idx = -1;
+	aPresent = ETrue;	
+	TSqlBufRIterator nameBufIt;
+	nameBufIt.Set(aNameBufFlat);
+	while(nameBufIt.Next())
+		{
+		++idx;
+		if(::CompareNoCase16(aName, nameBufIt.Text()) == 0)
+			{
+			return idx;	
+			}
+		}
+	return KErrNotFound;
+	}
+
+                   
+TInt CSqlStatementImpl::Index2Name(TInt aIndex, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent, TPtrC& aColName)
+	{
+	if( aCount == 0 || aIndex < 0 || aIndex >= aCount ) 
+		{
+		return KErrNotFound;	
+		}
+	TInt err = CheckNameBufPresent(aPresent, aNameBufFlat, aCount, aFunction);
+	if ( err != KErrNone ) 
+		{
+		return err;
+		}
+	aPresent = ETrue;	
+	TSqlBufRIterator nameBufIt;
+	nameBufIt.Set(aNameBufFlat);
+	nameBufIt.MoveTo(aIndex);
+	aColName.Set(nameBufIt.Text());
+	return KErrNone;
+	}
+
+/**
+Ensures that the specified names buffer is present on the client side.
+Name buffers are used for transporting parameter and column names.
+
+@return KErrNone if successfull or one of the system-wide error codes on error
+@internalComponent
+*/
+TInt CSqlStatementImpl::CheckNameBufPresent(TBool& aPresent, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction)
+	{
+	if(!aPresent)
+		{
+		aNameBufFlat.Close();
+		TInt err = aNameBufFlat.SetCount(aCount);
+		if(err != KErrNone)
+			{
+			return err;	
+			}
+		err = iSqlStmtSession.GetNames(aFunction, aNameBufFlat);
+		if(err != KErrNone)
+			{
+			return err;	
+			}
+		}
+	return KErrNone;
+	}
+
+
+/**
+Returns a buffer containing a ";" separated list with declared types of statement's columns.
+The caller is responsible for deleting the result buffer.
+
+@return HBufC buffer - column types list.
+*/
+HBufC* CSqlStatementImpl::GetDeclColumnTypesL()
+	{
+	return iSqlStmtSession.GetDeclColumnTypesL(iColumnCnt);
+	}
+