persistentstorage/sql/SRC/Server/SqlSrvStatement.cpp
changeset 0 08ec8eefde2f
child 9 667e88a979d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvStatement.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,790 @@
+// 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 <utf.h>					//CnvUtfConverter
+#include <e32math.h>
+#include "SqliteSymbian.h"			//sqlite3SymbianLastOsError()
+#include "sqlite3.h"
+#include "SqlSrvStatement.h"
+#include "SqlBufIterator.h"			//TSqlBufRIterator
+#include "SqlSrvResourceProfiler.h"
+#include "UTraceSql.h"
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////      local const data       ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//This is the name prefix which will be given to the nameless parameters.
+//For example, if the SQL string is:
+//   SELECT * FROM A WHERE ColA1 = ? AND ColA2 = ?
+//then the names which will be give to the parameters will be:
+//"?0" and "?1"
+_LIT(KNamelessParameter, "?");
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////                HSqlSrvStmtParamBuf                  //////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Destroys the parameter buffer.
+
+Virtual method.
+*/
+HSqlSrvStmtParamBuf::~HSqlSrvStmtParamBuf()
+	{
+	delete iBuf;
+	}
+
+/**
+Binds the parameter value.
+The buffer can be synch-ed if:
+ - this is the first synch operation;
+ - the bound statement object is still alive (not finalized);
+ - the current object is alive;
+ - the current object data is retrieved from an IPC stream;
+ 
+If none of the conditions above is true, the synch operation is no-op.
+
+Virtual method.
+*/
+void HSqlSrvStmtParamBuf::DoSynchL()
+	{
+	if(iSynchDone || !iAlive || iStatementFinalized || iBufType != HSqlSrvStmtParamBuf::EBufIpcStream)
+		{
+		return;	
+		}
+	iSynchDone = ETrue;
+	TBufBuf::DoSynchL();
+	iStatement.BindParamBufL(iParamIndex);
+	}
+
+/**
+Destroys the HSqlSrvStmtParamBuf instance.
+This method is a no-op if the statement is not finalized yet.
+
+Virtual method.
+*/
+void HSqlSrvStmtParamBuf::DoRelease()
+ 	{
+	iAlive = EFalse;
+ 	if(iStatementFinalized)
+ 		{//The bound statement has been finalized - destroy the current object then.
+ 		delete this;
+ 		}
+	}
+
+/**
+This function is called by the bound statement object to notify the current HSqlSrvStmtParamBuf object that the
+bound statement is about to be finalized. That means, when the "stream close" operation on the client side 
+makes an attempt to synch the HSqlSrvStmtParamBuf object, no attempt should be made to bound the parameter data,
+because the statement object is gone.
+After this call the bound statement objects seases to exist.
+
+Actions, performed by this method:
+ - if the buffer type is "simple bind", the buffer will be destroyed. No reason to keep it alive, there is no bound IPC
+   stream object on the client side;
+ - if the buffer type is an IPC stream buffer and the buffer is alive, that means: the bound statement object is about to be
+   finalized, but there is a bound client side IPC stream object that is still alive. In this case the buffer won't be destroyed,
+   but will be "told" that the bound statement is finalized, so when the client side IPC stream is closed, this object will get destroyed;
+ - if the buffer type is an IPC stream buffer and the buffer is "dead", that means there is no bound IPC stream object on the client
+   side and it is safe to destroy the buffer;
+
+*/ 	
+void HSqlSrvStmtParamBuf::NotifyStatementFinalized()
+	{
+	iStatementFinalized = ETrue;
+	if(iBufType == HSqlSrvStmtParamBuf::EBufSimpleBind || !iAlive)
+		{
+		DoRelease();	
+		}
+	}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////   CSqlSrvStatement class    ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Creates a new CSqlSrvStatement instance.
+
+The created CSqlSrvStatement instance will be placed in the cleanup stack.
+
+@param aDbHandle The database handle
+@param aSqlStmt 16-bit SQL statement, zero-terminated string
+@param aColumnCount Output parameter. It will be initialized with the column count.
+@param aParamCount Output parameter. It will be initialized with the parameter count.
+
+@return A pointer to the created CSqlSrvStatement instance.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KErrArgument, bad argument, for example - the SQL string contains more than one SQL statements.
+                  Note that the function may also leave with some other database specific 
+                  errors categorised as ESqlDbError.
+
+@panic SqlDb 4 In _DEBUG mode if aSqlStmt is not zero-terminated string.
+*/	
+CSqlSrvStatement* CSqlSrvStatement::NewLC(sqlite3* aDbHandle, const TDesC16& aSqlStmt, TInt& aColumnCount, TInt& aParamCount)
+	{
+	__SQLASSERT(aSqlStmt.Length() > 0 ? (TInt)aSqlStmt[aSqlStmt.Length() - 1] == 0 : ETrue, ESqlPanicBadArgument);
+	
+	CSqlSrvStatement* self = new (ELeave) CSqlSrvStatement;
+	CleanupStack::PushL(self);
+	self->ConstructL(aDbHandle, aSqlStmt);
+	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KSrvStmtCreated, self));
+	aColumnCount = self->iColumnCount;
+	aParamCount = self->iParamCount;
+	return self;
+	}
+	
+/**
+Creates a new CSqlSrvStatement instance.
+
+The created CSqlSrvStatement instance will be placed in the cleanup stack.
+
+@param aDbHandle The database handle
+@param aSqlStmt 8-bit SQL statement, zero-terminated string
+@param aColumnCount Output parameter. It will be initialized with the column count.
+@param aParamCount Output parameter. It will be initialized with the parameter count.
+
+@return A pointer to the created CSqlSrvStatement instance.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KErrArgument, bad argument, for example - the SQL string contains more than one SQL statements.
+                  Note that the function may also leave with some other database specific 
+                  errors categorised as ESqlDbError.
+
+@panic SqlDb 4 In _DEBUG mode if aSqlStmt is not zero-terminated string.
+*/	
+CSqlSrvStatement* CSqlSrvStatement::NewLC(sqlite3* aDbHandle, const TDesC8& aSqlStmt, TInt& aColumnCount, TInt& aParamCount)
+	{
+	__SQLASSERT(aSqlStmt.Length() > 0 ? (TInt)aSqlStmt[aSqlStmt.Length() - 1] == 0 : ETrue, ESqlPanicBadArgument);
+
+	CSqlSrvStatement* self = new (ELeave) CSqlSrvStatement;
+	CleanupStack::PushL(self);
+	self->ConstructL(aDbHandle, aSqlStmt);
+	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KSrvStmtCreated, self));
+	aColumnCount = self->iColumnCount;
+	aParamCount = self->iParamCount;
+	return self;
+	}
+	
+/**
+Destroys the allocated by CSqlSrvStatement instance memory and other resources.
+*/	
+CSqlSrvStatement::~CSqlSrvStatement()
+	{
+	DestroyParamBufArray();
+	iBufFlat.Close();
+	if(iStmtHandle)
+		{
+#ifdef SYMBIAN_TRACE_SQL_EVENTS
+		TInt scanCount = sqlite3_stmt_status(iStmtHandle, SQLITE_STMTSTATUS_FULLSCAN_STEP, ETrue);
+		TInt sortCount = sqlite3_stmt_status(iStmtHandle, SQLITE_STMTSTATUS_SORT, ETrue);
+		SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KSrvStmtStatus, this, scanCount, sortCount));
+#endif
+		(void)sqlite3_finalize(iStmtHandle);
+		}
+	}
+
+/**
+Sets SQL statement parameter values.
+
+Only parameters, which values are set by the client, will be processed.
+
+@param aParamBuf Flat buffer with parameter values.
+
+@leave KErrArgument, unknown parameter type;
+	   KSqlErrStmtExpired, statement handle expired.
+                  Note that the function may also leave with some other database specific 
+                  errors categorised as ESqlDbError.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+*/	
+void CSqlSrvStatement::BindL(const RSqlBufFlat& aParamBuf)
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	
+	(void)sqlite3SymbianLastOsError();//clear last OS error
+	if(sqlite3_expired(iStmtHandle))
+		{
+		__SQLLEAVE_IF_ERROR(KSqlErrStmtExpired);
+		}
+
+	TSqlBufRIterator it;
+	it.Set(aParamBuf);
+	TInt prmIdx = 0;
+	
+	TInt err = SQLITE_OK;
+	while(it.Next() && err == SQLITE_OK)
+		{
+		++prmIdx;//the first SQLITE parameter index is 1
+		if(it.IsPresent())
+			{
+			switch(it.Type())
+ 				{
+				case ESqlInt:
+					err = sqlite3_bind_int(iStmtHandle, prmIdx, it.Int());
+					break;
+				case ESqlInt64:
+					err = sqlite3_bind_int64(iStmtHandle, prmIdx, it.Int64());
+					break;
+				case ESqlReal: 
+					err = sqlite3_bind_double(iStmtHandle, prmIdx, it.Real());
+					break;
+				case ESqlText: 
+					//SQLITE_STATIC is used as an argument, because the text data will be kept and can be used by the next bind call
+					{
+					TPtrC text = it.Text();
+					TPtrC8 prmDataCopy(reinterpret_cast <const TUint8*> (text.Ptr()), text.Length() * sizeof(TUint16));
+					prmDataCopy.Set(CopyAndStoreParamL(prmIdx - 1, HSqlSrvStmtParamBuf::EText16, prmDataCopy));
+					err = sqlite3_bind_text16(iStmtHandle, prmIdx, prmDataCopy.Ptr(), prmDataCopy.Length(), SQLITE_STATIC);
+					}
+					break;
+				case ESqlBinary:
+					//SQLITE_STATIC is used as an argument, because the blob data will be kept and can be used by the next bind call
+					{
+					TPtrC8 prmDataCopy = CopyAndStoreParamL(prmIdx - 1, HSqlSrvStmtParamBuf::EBinary, it.Binary());
+					err = sqlite3_bind_blob(iStmtHandle, prmIdx, prmDataCopy.Ptr(), prmDataCopy.Length(), SQLITE_STATIC);
+					}
+					break;
+				case ESqlNull:
+					err = sqlite3_bind_null(iStmtHandle, prmIdx);
+					break;
+				case ESqlZeroBlob:
+					err = sqlite3_bind_zeroblob(iStmtHandle, prmIdx, it.Int());
+					break;
+				default:
+					__SQLLEAVE(KErrArgument);//unknown parameter type
+					break;
+				}
+			}//end of - if(it.IsPresent())
+		}//end of - while(it.Next() && err == SQLITE_OK)
+	err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
+	__SQLLEAVE_IF_ERROR(err);
+	}
+
+/**
+Collects column names in a flat buffer and returns a reference to the buffer. 
+
+@return A const reference to a flat buffer containing the column values.
+
+@leave KErrNoMemory, an out of memory condition has occurred.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+*/	
+const RSqlBufFlat& CSqlSrvStatement::ColumnNamesL()
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	iBufFlatType = static_cast <TSqlBufFlatType> (-1);
+	__SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iColumnCount));
+	TSqlBufWIterator it;
+	it.Set(iBufFlat);
+	TInt colIdx = -1;
+	while(it.Next())
+		{
+		++colIdx;//the first SQLITE column index is 0
+		const TUint16* name = reinterpret_cast <const TUint16*> (__SQLLEAVE_IF_NULL(const_cast <void*> (sqlite3_column_name16(iStmtHandle, colIdx))));
+		TPtrC ptr(name, User::StringLength(name));
+		__SQLLEAVE_IF_ERROR(it.SetText(ptr));
+		}
+	iBufFlatType = ESqlColumnNamesBuf;
+	SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
+	return iBufFlat;
+	}
+
+/**
+Collects parameter names in a flat buffer and returns a reference to the buffer. 
+
+@return A const reference to a flat buffer containing the column values.
+
+@leave KErrNoMemory, an out of memory condition has occurred.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+*/	
+const RSqlBufFlat& CSqlSrvStatement::ParamNamesL()
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	iBufFlatType = static_cast <TSqlBufFlatType> (-1);
+	__SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iParamCount));
+	TSqlBufWIterator it;
+	it.Set(iBufFlat);
+	TInt prmIdx = 0;
+	while(it.Next())
+		{
+		++prmIdx;//the first SQLITE parameter index is 1
+		const TUint8* name8 = reinterpret_cast <const TUint8*> (sqlite3_bind_parameter_name(iStmtHandle, prmIdx));
+		if(name8)
+			{
+			HBufC* name = CnvUtfConverter::ConvertToUnicodeFromUtf8L(TPtrC8(name8, User::StringLength(name8)));
+			TInt err = it.SetText(name->Des());
+			delete name;
+			__SQLLEAVE_IF_ERROR(err);
+			}
+		else //nameless parameter case
+			{
+			//The parameter name in this case will be formatted as "?<num>", where <num> is the parameter index.
+			TBuf<5> prmName;
+			prmName.Append(KNamelessParameter);
+			prmName.AppendNum((TInt64)(prmIdx - 1));
+			__SQLLEAVE_IF_ERROR(it.SetText(prmName));
+			}
+		}
+	iBufFlatType = ESqlParamNamesBuf;
+	SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
+	return iBufFlat;
+	}
+	
+/**
+Collects the column values in a flat buffer and returns a reference to the buffer. 
+
+@leave KErrNoMemory, an out of memory condition has occurred.
+
+@return A const reference to a flat buffer containing the column values.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object
+*/	
+const RSqlBufFlat& CSqlSrvStatement::ColumnValuesL()
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	
+	iBufFlatType = static_cast <TSqlBufFlatType> (-1);
+	iBufFlat.SetCount(iColumnCount);
+	TSqlBufWIterator it;
+	it.Set(iBufFlat);
+	TInt colIdx = -1;
+	
+	while(it.Next())
+		{
+		++colIdx;//the first SQLITE column index is 0
+		TInt colType = sqlite3_column_type(iStmtHandle, colIdx);
+		switch(colType)
+			{
+			case SQLITE_INTEGER:
+				{
+				TInt64 val = sqlite3_column_int64(iStmtHandle, colIdx);
+				__SQLLEAVE_IF_ERROR(val == TInt64(TInt32(val)) ? it.SetInt(static_cast <TInt> (val)) : it.SetInt64(val));
+				}
+				break;
+			case SQLITE_FLOAT:
+				__SQLLEAVE_IF_ERROR(it.SetReal(sqlite3_column_double(iStmtHandle, colIdx)));
+				break;
+			case SQLITE_TEXT:
+				{
+				TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, colIdx) / sizeof(TUint16);
+				if(charLength >= KSqlMaxDesLen)
+					{
+					it.SetAsNotPresent(ESqlText, charLength);
+					}
+				else
+					{
+					__SQLLEAVE_IF_ERROR(it.SetText(TPtrC16(reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, colIdx)), charLength)));
+					}
+				}
+				break;
+			case SQLITE_BLOB:
+				{
+				TInt byteLength = sqlite3_column_bytes(iStmtHandle, colIdx);
+				if(byteLength >= KSqlMaxDesLen)
+					{
+					it.SetAsNotPresent(ESqlBinary, byteLength);
+					}
+				else
+					{
+					__SQLLEAVE_IF_ERROR(it.SetBinary(TPtrC8(reinterpret_cast <const TUint8*> (sqlite3_column_blob(iStmtHandle, colIdx)), byteLength)));
+					}
+				}
+				break;
+			case SQLITE_NULL:
+				it.SetNull();
+				break;
+			default:
+				__SQLASSERT(EFalse, ESqlPanicInternalError);
+				break;
+			}//end of switch(...)
+		}//end of - while(it.Next())
+	iBufFlatType = ESqlColumnValuesBuf;
+	SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
+	return iBufFlat;
+	}
+
+/**
+This method sets aColumnSource parameter to point to the column data.
+
+@param aColumnIndex Column Index, zero based. 
+@param aColumnSource Output parameter. It is set to point to the column data.
+
+@return KErrNone, the operation completed successfully;
+		KErrArgument, the refered by aColumnIndex index column is not a binary or text column.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+*/	
+TInt CSqlSrvStatement::ColumnSource(TInt aColumnIndex, TPtrC8& aColumnSource) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	TInt colType = sqlite3_column_type(iStmtHandle, aColumnIndex);
+	if(colType == SQLITE_TEXT)
+		{
+		const void* text = sqlite3_column_text16(iStmtHandle, aColumnIndex);
+		TInt length  = sqlite3_column_bytes16(iStmtHandle, aColumnIndex);
+		aColumnSource.Set(reinterpret_cast <const TUint8*> (text), length);
+		}
+	else if(colType == SQLITE_BLOB)
+		{
+		const void* data = sqlite3_column_blob(iStmtHandle, aColumnIndex);
+		TInt length  = sqlite3_column_bytes(iStmtHandle, aColumnIndex);
+		aColumnSource.Set(reinterpret_cast <const TUint8*> (data), length);
+		}
+	else
+		{
+		return KErrArgument;	
+		}
+	return KErrNone;
+	}
+
+/**
+Retrieves from the SQLITE library columns and parameters count.
+
+@panic SqlDb 4 In _DEBUG mode. aDbHandle is NULL.
+*/	
+void CSqlSrvStatement::DoCommonConstructL()
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	iColumnCount = sqlite3_column_count(iStmtHandle);
+	iParamCount = sqlite3_bind_parameter_count(iStmtHandle);
+	__SQLLEAVE_IF_ERROR(iBufFlat.SetCount(Max(iColumnCount, iParamCount)));
+	}
+
+/**
+Destroys the parameter buffer array (used for text or binary parameters).
+Before the array destruction, each array member is notified that the statement is about to be finalized.
+*/
+void CSqlSrvStatement::DestroyParamBufArray()
+	{
+	TInt idx = iParamBufArray.Count();
+	while(--idx >= 0)
+		{
+		if(iParamBufArray[idx])
+			{
+			iParamBufArray[idx]->NotifyStatementFinalized();	
+			}
+		}
+	iParamBufArray.Close();
+	}
+	
+/**
+Binds a streamed text or binary parameter value.
+
+@param aParamIndex The text/binary parameter index
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+	   KSqlErrStmtExpired, statement handle has expired.
+                  Note that the function may also leave with some other database specific 
+                  errors categorised as ESqlDbError.
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. No parameter buffer has been created yet for this parameter.
+@panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
+*/
+void CSqlSrvStatement::BindParamBufL(TInt aParamIndex)
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), ESqlPanicBadArgument);
+	__SQLASSERT(aParamIndex < iParamBufArray.Count(), ESqlPanicBadArgument);
+	__SQLASSERT(iParamBufArray[aParamIndex] != NULL, ESqlPanicBadArgument);
+	(void)sqlite3SymbianLastOsError();//clear last OS error
+	if(sqlite3_expired(iStmtHandle))
+		{
+		__SQLLEAVE_IF_ERROR(KSqlErrStmtExpired);
+		}
+	//Bind the parameter value.
+	//SQLITE_STATIC is used as an argument, because the text/blob data will be kept and can be used by the next bind call
+	HSqlSrvStmtParamBuf& paramBuf = *iParamBufArray[aParamIndex];
+	const TPtrC8 paramData(paramBuf.Data());
+	SQLPROFILER_REPORT_ALLOC(paramData.Length());
+	TInt err = KErrNone;
+	++aParamIndex;//SQLite uses positive parameter indexes, the SQL server - parameter indexes begin from 0
+	switch(paramBuf.DataType())
+		{
+		case HSqlSrvStmtParamBuf::EText16:
+			//sqlite3_bind_text16() expects 4-th argument to be the bytes count, not the characters count.
+			err = sqlite3_bind_text16(iStmtHandle, aParamIndex, paramData.Ptr(), paramData.Length(), SQLITE_STATIC);
+			break;
+		case HSqlSrvStmtParamBuf::EBinary:
+		default:
+			err = sqlite3_bind_blob(iStmtHandle, aParamIndex, paramData.Ptr(), paramData.Length(), SQLITE_STATIC);
+			break;
+		}
+	err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
+	__SQLLEAVE_IF_ERROR(err);
+	}
+
+/**
+@return Represents the content of the column identified by aColIdx as integer value.
+		If the current column type does not refer to an integer, then 
+		the function will do a data conversion as described in the table which can be found
+		in SqlDb.h file.
+@see RSqlStatement
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
+*/
+TInt CSqlSrvStatement::ColumnInt(TInt aColIdx) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
+	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
+	switch(colType)
+		{
+		case SQLITE_FLOAT:
+			{
+			TReal roundVal;
+			TInt err = Math::Round(roundVal, sqlite3_column_double(iStmtHandle, aColIdx), 0);
+			if(err != KErrNone)
+				{
+				return KMinTInt;
+				}
+			TRealX val(roundVal);
+			return static_cast <TInt> (val);
+			}
+		case SQLITE_NULL:
+		case SQLITE_TEXT:
+		case SQLITE_BLOB:
+			return 0;
+		default:			//int, int64
+			{
+			TInt64 val = sqlite3_column_int64(iStmtHandle, aColIdx);
+			return val == (TInt)val ? (TInt)val : (val < KMinTInt ? KMinTInt : KMaxTInt);
+			}
+		}
+	}
+	
+/**
+@return Represents the content of the column identified by aColIdx as 64-bit integer value.
+		If the current column type does not refer to a 64-bit integer, then 
+		the function will do a data conversion as described in the table which can be found
+		in SqlDb.h file.
+@see RSqlStatement
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
+*/
+TInt64 CSqlSrvStatement::ColumnInt64(TInt aColIdx) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
+	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
+	switch(colType)
+		{
+		case SQLITE_FLOAT:
+			{
+			TReal roundVal;
+			TInt err = Math::Round(roundVal, sqlite3_column_double(iStmtHandle, aColIdx), 0);
+			if(err != KErrNone)
+				{
+				return KMinTInt64;
+				}
+			TRealX val(roundVal);
+			return static_cast <TInt64> (val);
+			}
+		case SQLITE_NULL:
+		case SQLITE_TEXT:
+		case SQLITE_BLOB:
+			return 0;
+		default:			//int, int64
+			return sqlite3_column_int64(iStmtHandle, aColIdx);
+		}
+	}
+	
+/**
+@return Represents the content of the column identified by aColIdx as real value.
+		If the current column type does not refer to a real, then 
+		the function will do a data conversion as described in the table which can be found
+		in SqlDb.h file.
+@see RSqlStatement
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
+*/
+TReal CSqlSrvStatement::ColumnReal(TInt aColIdx) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
+	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
+	switch(colType)
+		{
+		case SQLITE_INTEGER:
+			{
+			TRealX val(sqlite3_column_int64(iStmtHandle, aColIdx));	
+			return static_cast <TReal> (val);
+			}
+		case SQLITE_NULL:
+		case SQLITE_TEXT:
+		case SQLITE_BLOB:
+			return 0.0;
+		default:
+			return sqlite3_column_double(iStmtHandle, aColIdx);
+		}
+	}
+	
+/**
+Represents the content of the column identified by aColIdx as text (16 bit) descriptor.
+If the current column type does not refer to a text block of data, then 
+the function will do a data conversion as described in the table which can be found
+in SqlDb.h file.
+		
+@see RSqlStatement
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
+*/
+TPtrC CSqlSrvStatement::ColumnText(TInt aColIdx) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
+	TPtrC res;
+	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
+	if(colType == SQLITE_TEXT)
+		{
+		TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, aColIdx) / sizeof(TUint16);
+		res.Set(reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, aColIdx)), charLength);
+		}
+	return res;
+	}
+	
+/**
+Represents the content of the column identified by aColIdx as binary (8 bit) descriptor.
+If the current column type does not refer to a binary block of data, then 
+the function will do a data conversion as described in the table which can be found
+in SqlDb.h file.
+                      
+@see RSqlStatement
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
+*/
+TPtrC8 CSqlSrvStatement::ColumnBinary(TInt aColIdx) const
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
+	TPtrC8 res;
+	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
+	if(colType == SQLITE_BLOB)
+		{
+		TInt byteLength = sqlite3_column_bytes(iStmtHandle, aColIdx);
+		res.Set(reinterpret_cast <const TUint8*> (sqlite3_column_blob(iStmtHandle, aColIdx)), byteLength);
+		}
+	return res;
+	}
+
+/**
+This function is used by the DBMS emulation library only.
+The function retrieves the declared column types from the SQLITE library, compiles them in a single string
+and then returns the string to the caller.
+
+The function also initializes iColumnText8 array, where particular array element with index "idx" will 
+be set to 1, if the column with index "idx" is a 8-bit text column.
+
+@return A pointer to a heap allocated HBufC object with the delcared column types. The caller is responsible
+		for the HBufC object destruction.
+*/
+HBufC* CSqlSrvStatement::GetDeclColumnTypesL()
+	{
+	HBufC* buf = HBufC::NewL(iColumnCount * 20);//20 as length is enough for a single column type text
+	TPtr ptr = buf->Des();
+	for(TInt i=0;i<iColumnCount;++i)
+		{
+		const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, i));
+		if(declTypeTxt)
+			{
+			TPtrC type(declTypeTxt, User::StringLength(declTypeTxt));
+			ptr.Append(type);
+			}
+		ptr.Append(TChar(';'));
+		}
+	return buf;
+	}
+
+/**
+Creates a new HSqlSrvStmtParamBuf object.
+
+@param aParameterIndex Parameter index, zero based.
+@param aDataType Parameter value type - binary, text8 or text16.
+@param aIsStreamBuf True if the param data will be retrieved from an IPC stream
+
+@return A pointer to the created HSqlSrvStmtParamBuf instance.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+*/
+HSqlSrvStmtParamBuf* CSqlSrvStatement::GetParamBufL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, 
+													HSqlSrvStmtParamBuf::TBufType aBufType)
+	{
+	__SQLASSERT(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), ESqlPanicBadArgument);
+	ExtendParamBufArrayL(aParamIndex);
+	HSqlSrvStmtParamBuf*& paramBuf = iParamBufArray[aParamIndex];
+	if(paramBuf)
+		{//Reset and reuse the existing buffer
+		__SQLASSERT(paramBuf->ParamIndex() == aParamIndex, ESqlPanicInternalError);
+		paramBuf->Reset(aDataType, aBufType);	
+		}
+	else
+		{
+		paramBuf = HSqlSrvStmtParamBuf::NewL(*this, aParamIndex, aDataType, aBufType);
+		}
+	return paramBuf;
+	}
+
+/**
+This function will extend the iParamBufArray array (filling the new array items with NULL), if it is needed - 
+to ensure that there is enough place for the buffer for the parameter identified by aParamIndex.
+
+@param aParamIndex The parameter index
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
+*/
+void CSqlSrvStatement::ExtendParamBufArrayL(TInt aParamIndex)
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), ESqlPanicBadArgument);
+	TInt ext = aParamIndex - iParamBufArray.Count() + 1;
+	while(ext-- > 0)
+		{
+		__SQLLEAVE_IF_ERROR(iParamBufArray.Append(NULL));
+		}
+	}
+
+/**
+This function will create a copy of the aParamValue and store it in the iParamBufArray array for later use.
+The reason: once bound, the parameter value can be used multiple times by the SQLite if it is not set explicitly again.
+
+@param aParamIndex The parameter index
+@param aDataType Parameter value type - binary, text8 or text16.
+@param aParamValue The parameter value
+
+@return 8-bit descriptor to the stored parameter value
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+                     
+@panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
+@panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
+*/
+TPtrC8 CSqlSrvStatement::CopyAndStoreParamL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, const TDesC8& aParamValue)
+	{
+	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
+	__SQLASSERT(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), ESqlPanicBadArgument);
+	HSqlSrvStmtParamBuf* paramBuf = GetParamBufL(aParamIndex, aDataType, HSqlSrvStmtParamBuf::EBufSimpleBind);
+	return paramBuf->SetDataL(aParamValue);
+	}