persistentstorage/sql/SRC/Client/SqlStatementImpl.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "SqlStatementImpl.h" 	//CSqlStatementImpl
       
    17 #include "SqlDatabaseImpl.h"	//CSqlDatabaseImpl::Session()
       
    18 
       
    19 //Constants
       
    20 
       
    21 _LIT(KSemiColon,";");
       
    22 
       
    23 _LIT(KTextKWD, 	"TEXT");
       
    24 _LIT(KCharKWD, 	"CHAR");
       
    25 _LIT(KClobKWD, 	"CLOB");
       
    26 
       
    27 _LIT(KBinaryKWD,"BINARY");
       
    28 _LIT(KBlobKWD,	"BLOB");
       
    29 
       
    30 _LIT(KRealKWD, 	"REAL");
       
    31 _LIT(KFloatKWD, "FLOAT");
       
    32 _LIT(KDoubleKWD,"DOUBLE");
       
    33 
       
    34 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    35 //////////////////////////             RSqlLongColumnColl        ////////////////////////////////////////////
       
    36 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    37 
       
    38 /**
       
    39 This "comparison" function is used for searching a particular column value, identified by aIndex, in the long column 
       
    40 values collection.
       
    41 @param aIndex An integer pointer to long column index value
       
    42 @param aData A reference to particular elemt of the long column values collection
       
    43 @return True of the index of aData item is the same as *aIndex, false otherwise
       
    44 @panic SqlDb 4 In _DEBUG mode, aIndex is NULL.
       
    45 @panic SqlDb 4 In _DEBUG mode, *aIndex value is negative.
       
    46 */
       
    47 TBool RSqlLongColumnColl::TData::Compare(const TInt* aIndex, const RSqlLongColumnColl::TData& aData)
       
    48 	{
       
    49 	__SQLASSERT(aIndex != NULL, ESqlPanicBadArgument);
       
    50 	__SQLASSERT(*aIndex >= 0, ESqlPanicBadArgument);
       
    51 	return *aIndex == aData.iIndex;
       
    52 	}
       
    53 
       
    54 /**
       
    55 Reads a long column value, identified by aColumnIndex parameter, from the server and stores the value in the collection.
       
    56 @param aReader A RSqlLongColumnColl::TColumnReader object, which performs the "read column value" operation.
       
    57 @param aColumnIndex Column index
       
    58 @param aColumnSize The column size in bytes
       
    59 @panic SqlDb 4 In _DEBUG mode, aColumnIndex value is negative.
       
    60 @panic SqlDb 4 In _DEBUG mode, aColumnSize is less than KSqlMaxDesLen (not a long column value)
       
    61 @return KErrNone The call has completed successfully;
       
    62 		KErrNoMemory Out of memory;
       
    63         Note that other system-wide or database specific error codes may also be returned.
       
    64 */
       
    65 TInt RSqlLongColumnColl::Append(RSqlLongColumnColl::TColumnReader& aReader, TInt aColumnIndex, TInt aColumnSize)
       
    66 	{
       
    67 	__SQLASSERT(aColumnIndex >= 0, ESqlPanicBadArgument);
       
    68 	__SQLASSERT(aColumnSize >= KSqlMaxDesLen, ESqlPanicBadArgument);
       
    69 	LONGCOL_INVARIANT();
       
    70 	HBufC8* colBuf = HBufC8::New(aColumnSize);
       
    71 	if(!colBuf)
       
    72 		{
       
    73 		return KErrNoMemory;	
       
    74 		}
       
    75 	TPtr8 ptr = colBuf->Des();
       
    76 	TInt err = aReader.Read(aColumnIndex, ptr);
       
    77 	if(err == KErrNone)
       
    78 		{
       
    79 		err = iValues.Append(RSqlLongColumnColl::TData(aColumnIndex, colBuf));	
       
    80 		}
       
    81 	if(err != KErrNone)
       
    82 		{
       
    83 		delete colBuf;	
       
    84 		}
       
    85 	LONGCOL_INVARIANT();
       
    86 	return err;
       
    87 	}
       
    88 	
       
    89 #ifdef _DEBUG
       
    90 /**
       
    91 RSqlLongColumnColl invariant.
       
    92 The collection cannot have two column values with the same column index.
       
    93 The collection cannot have NULL column value, or negative column index.
       
    94 */
       
    95 void RSqlLongColumnColl::Invariant() const
       
    96 	{
       
    97 	for(TInt i=iValues.Count()-1;i>=0;--i)
       
    98 		{
       
    99 		const RSqlLongColumnColl::TData& data = iValues[i];
       
   100 		__SQLASSERT(data.iIndex >= 0, ESqlPanicInternalError);
       
   101 		__SQLASSERT(data.iData != NULL, ESqlPanicInternalError);
       
   102 		for(TInt j=i-1;j>=0;--j)
       
   103 			{
       
   104 			__SQLASSERT(data.iIndex != iValues[j].iIndex, ESqlPanicInternalError);
       
   105 			}
       
   106 		}
       
   107 	}
       
   108 #endif
       
   109 
       
   110 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   111 //////////////////////////           CSqlStatementImpl           ////////////////////////////////////////////
       
   112 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   113 
       
   114 /**
       
   115 RSqlLongColumnColl::TColumnReader derived class, which implements the pure virtual RSqlLongColumnColl::TColumnReader::Read().
       
   116 The class is used for retrieving long column values from the server.
       
   117 @internalComponent
       
   118 */
       
   119 NONSHARABLE_STRUCT(TSqlLongColumnReader) : public RSqlLongColumnColl::TColumnReader
       
   120 	{
       
   121 	TSqlLongColumnReader(RSqlStatementSession& aStmtSession) :
       
   122 		iStmtSession(aStmtSession)
       
   123 		{
       
   124 		}
       
   125 	virtual TInt Read(TInt aColumnIndex, TDes8& aBuf)
       
   126 		{
       
   127 		return iStmtSession.ReadColumnValue(aColumnIndex, aBuf);
       
   128 		}
       
   129 	RSqlStatementSession	iStmtSession;
       
   130 	};
       
   131 
       
   132 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   133 //////////////////////////           CSqlStatementImpl           ////////////////////////////////////////////
       
   134 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   135 
       
   136 /**
       
   137 Frees the allocated memory and other resources.
       
   138 */
       
   139 CSqlStatementImpl::~CSqlStatementImpl()
       
   140 	{
       
   141 	iDeclaredColumnTypes.Close();
       
   142 	iLongColumnColl.Close();
       
   143 	iParamValueBuf.Close();
       
   144 	iParamNameBuf.Close();
       
   145 	iColumnValueBuf.Close();
       
   146 	iColumnNameBuf.Close();
       
   147 	iSqlStmtSession.Close();
       
   148 	}
       
   149 
       
   150 
       
   151 
       
   152 /**
       
   153 Resets the prepared SQL statement back to its initial state and makes it ready for re-execution.
       
   154 The parameters of the SQL statement retain their values.
       
   155 If CSqlStatementImpl object processes parametrized SQL statement, the parameter values can be bound after 
       
   156 the Reset() call.
       
   157 
       
   158 The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
       
   159 cannot be used until the next successful Next() call.
       
   160 
       
   161 @return KSqlErrStmtExpired, statement expired (if new functions or collating sequences are 
       
   162 							registered or if an authorizer function is added or changed);
       
   163 		KErrNone, the operation has completed successfully.
       
   164 
       
   165 @see RSqlStatement::Reset()
       
   166 */
       
   167 TInt CSqlStatementImpl::Reset()
       
   168 	{
       
   169 	iState = CSqlStatementImpl::EUnknown;
       
   170 	iLongColumnColl.Reset();
       
   171 	if(iParamCnt > 0)
       
   172 		{
       
   173 		iParamValueBuf.ResetAndMinimize();
       
   174 		}
       
   175 	return iSqlStmtSession.Reset();
       
   176 	}
       
   177 
       
   178 /**
       
   179 Executes the prepared DDL/DML SQL statement. 
       
   180 
       
   181 If the SQL statement contains parameters, their values will be bound right before the execution.
       
   182 
       
   183 The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
       
   184 cannot be used until the next successful Next() call.
       
   185 
       
   186 @return >=0, The operation has completed successfully. The number of database rows that were 
       
   187 			 changed/inserted/deleted by the most recently completed DDL/DML sql statement.
       
   188 			 Exception: If the executed statement is "DELETE FROM <table>", then the function returns 0 
       
   189 			 if the operation has completed successfully (disregarding the number of the deleted rows);
       
   190 	    KSqlErrStmtExpired, statement has expired (if new functions or collating sequences are 
       
   191 							registered or if an authorizer function is added or changed);
       
   192 		KErrNoMemory, an out of memory condition has occurred.
       
   193                       Note that database specific errors categorised as ESqlDbError, and
       
   194                       other system-wide error codes may also be returned.
       
   195 
       
   196 @see RSqlStatement::Exec()
       
   197 */
       
   198 TInt CSqlStatementImpl::Exec()
       
   199 	{
       
   200 	iState = CSqlStatementImpl::EUnknown;
       
   201 	TInt rc = 0;
       
   202 	if(iBound)
       
   203 		{
       
   204 		rc = iSqlStmtSession.Exec();	
       
   205 		}
       
   206 	else
       
   207 		{
       
   208 		rc = iSqlStmtSession.BindExec(iParamValueBuf);
       
   209 		iBound = ETrue;
       
   210 		iParamValueBuf.ResetAndMinimize();
       
   211 		}
       
   212 	return rc;
       
   213 	}
       
   214 
       
   215 /**
       
   216 Executes the prepared DDL/DML SQL statement asynchronously. 
       
   217 
       
   218 If the SQL statement contains parameters, their values will be bound right before the execution.
       
   219 
       
   220 The method sets the internal object's state to CSqlStatementImpl::EUnknown. The column data accessors
       
   221 cannot be used until the next successful Next() call.
       
   222 
       
   223 @param aStatus Completion status of asynchronous request, one of the following:
       
   224 		 >=0, The operation has completed successfully. The number of database rows that were 
       
   225 		   	   changed/inserted/deleted by the most recently completed DDL/DML sql statement.
       
   226 			 Exception: If the executed statement is "DELETE FROM <table>", then the function returns 0 
       
   227 			 if the operation has completed successfully (disregarding the number of the deleted rows);
       
   228          KSqlErrStmtExpired, the SQL statement has expired (if new functions or
       
   229                             collating sequences have been registered or if an
       
   230                             authorizer function has been added or changed);
       
   231          KErrNoMemory, an out of memory condition has occurred - the statement
       
   232                       will be reset.
       
   233                       Note that aStatus may be set with database specific errors categorised as ESqlDbError, 
       
   234                       and other system-wide error codes.
       
   235 
       
   236 
       
   237 @see RSqlStatement::Exec()
       
   238 */
       
   239 void CSqlStatementImpl::Exec(TRequestStatus& aStatus)
       
   240 	{
       
   241 	iState = CSqlStatementImpl::EUnknown;
       
   242 	if(iBound)
       
   243 		{
       
   244 		iSqlStmtSession.Exec(aStatus);
       
   245 		}
       
   246 	else
       
   247 		{
       
   248 		iSqlStmtSession.BindExec(iParamValueBuf, aStatus);
       
   249 		iBound = ETrue;
       
   250 		//Here: it is not possible to reset iParamValueBuf for "safety", because this is an asynchronous call
       
   251 		//      and the buffer content has to be preserved until the operation completes.
       
   252 		}
       
   253 	}
       
   254 
       
   255 /**
       
   256 Retrieves a record.
       
   257 
       
   258 If the prepared SQL statement is a "SELECT" statement, and is expected to
       
   259 return a set of records, then this function can be used to retrieve that record data.
       
   260 
       
   261 If the SQL statement contains parameters, then their values must be bound before
       
   262 this function is called.
       
   263 
       
   264 If the call to this function completes successfully, i.e. it returns
       
   265 with KSqlAtRow, then this CSqlStatementImpl object contains the record data, and 
       
   266 this data will remain valid for access until another call is made to any
       
   267 CSqlStatementImpl function.
       
   268 
       
   269 The record data can be accessed using the following functions:
       
   270 - CSqlStatementImpl::ColumnType()
       
   271 - CSqlStatementImpl::ColumnSize()
       
   272 - CSqlStatementImpl::Column<Type>()
       
   273 
       
   274 @return KSqlAtRow,      the record data is ready for processing by the caller;
       
   275         KSqlAtEnd,      there is no more record data;
       
   276         KSqlErrBusy,    the database file is locked;
       
   277         KErrNoMemory,   an out of memory condition has occurred - the statement
       
   278                         will be reset;
       
   279         KSqlErrGeneral, a run-time error has occured - this function must not
       
   280                         be called again;        
       
   281         KSqlErrMisuse,  this function has been called after a previous call
       
   282                         returned KSqlAtEnd or KSqlErrGeneral.
       
   283         KSqlErrStmtExpired, the SQL statement has expired (if new functions or
       
   284                             collating sequences have been registered or if an
       
   285                             authorizer function has been added or changed);
       
   286 
       
   287 @see RSqlStatement::Next()
       
   288 */
       
   289 TInt CSqlStatementImpl::Next()
       
   290 	{
       
   291 	iLongColumnColl.Reset();
       
   292 	iColumnValueBuf.ResetAndMinimize();
       
   293 	iState = CSqlStatementImpl::EUnknown;
       
   294 	TInt err = KErrNone;
       
   295 	if(iBound)
       
   296 		{
       
   297 		err = iSqlStmtSession.Next(iColumnValueBuf);
       
   298 		}
       
   299 	else
       
   300 		{
       
   301 		err = iSqlStmtSession.BindNext(iParamValueBuf, iColumnValueBuf);
       
   302 		iBound = ETrue;
       
   303 		iParamValueBuf.ResetAndMinimize();
       
   304 		}
       
   305 	iColumnValBufIt.Set(iColumnValueBuf);
       
   306 	if(err == KSqlAtRow)
       
   307 		{
       
   308 		iState = CSqlStatementImpl::EAtRow;
       
   309 		}
       
   310 	return err;
       
   311 	}
       
   312 
       
   313 /**
       
   314 Implements RSqlStatement::BindNull().
       
   315 
       
   316 @panic SqlDb 5 Parameter index out of bounds.
       
   317 
       
   318 @see RSqlStatement::BindNull()
       
   319 */	
       
   320 TInt CSqlStatementImpl::BindNull(TInt aParamIndex)
       
   321 	{
       
   322 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   323 	iBound = EFalse;
       
   324 	iParamValBufIt.MoveTo(aParamIndex);
       
   325 	iParamValBufIt.SetNull();
       
   326 	return KErrNone;
       
   327 	}
       
   328 	
       
   329 /**
       
   330 Implements RSqlStatement::BindInt().
       
   331 
       
   332 @panic SqlDb 5 Parameter index out of bounds.
       
   333 
       
   334 @see RSqlStatement::BindInt()
       
   335 */	
       
   336 TInt CSqlStatementImpl::BindInt(TInt aParamIndex, TInt aParamValue)
       
   337 	{
       
   338 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   339 	iBound = EFalse;
       
   340 	iParamValBufIt.MoveTo(aParamIndex);
       
   341 	return iParamValBufIt.SetInt(aParamValue);
       
   342 	}
       
   343 	
       
   344 /**
       
   345 Implements RSqlStatement::BindInt64().
       
   346 
       
   347 @panic SqlDb 5 Parameter index out of bounds.
       
   348 
       
   349 @see RSqlStatement::BindInt64()
       
   350 */	
       
   351 TInt CSqlStatementImpl::BindInt64(TInt aParamIndex, TInt64 aParamValue)
       
   352 	{
       
   353 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   354 	iBound = EFalse;
       
   355 	iParamValBufIt.MoveTo(aParamIndex);
       
   356 	return iParamValBufIt.SetInt64(aParamValue);
       
   357 	}
       
   358 	
       
   359 /**
       
   360 Implements RSqlStatement::BindReal().
       
   361 
       
   362 @panic SqlDb 5 Parameter index out of bounds.
       
   363 
       
   364 @see RSqlStatement::BindReal()
       
   365 */	
       
   366 TInt CSqlStatementImpl::BindReal(TInt aParamIndex, TReal aParamValue)
       
   367 	{
       
   368 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   369 	iBound = EFalse;
       
   370 	iParamValBufIt.MoveTo(aParamIndex);
       
   371 	return iParamValBufIt.SetReal(aParamValue);
       
   372 	}
       
   373 	
       
   374 /**
       
   375 Implements RSqlStatement::BindText().
       
   376 
       
   377 @panic SqlDb 5 Parameter index out of bounds.
       
   378 
       
   379 @see RSqlStatement::BindText()
       
   380 */	
       
   381 TInt CSqlStatementImpl::BindText(TInt aParamIndex, const TDesC& aParamText)
       
   382 	{
       
   383 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   384 	iBound = EFalse;
       
   385 	iParamValBufIt.MoveTo(aParamIndex);
       
   386 	return iParamValBufIt.SetText(aParamText);
       
   387 	}
       
   388 	
       
   389 /**
       
   390 Implements RSqlStatement::BindBinary().
       
   391 
       
   392 @panic SqlDb 5 Parameter index out of bounds.
       
   393 
       
   394 @see RSqlStatement::BindBinary()
       
   395 */	
       
   396 TInt CSqlStatementImpl::BindBinary(TInt aParamIndex, const TDesC8& aParamData)
       
   397 	{
       
   398 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   399 	iBound = EFalse;
       
   400 	iParamValBufIt.MoveTo(aParamIndex);
       
   401 	return iParamValBufIt.SetBinary(aParamData);
       
   402 	}
       
   403 
       
   404 /**
       
   405 Implements RSqlStatement::BindZeroBlob().
       
   406 
       
   407 @panic SqlDb 5 Parameter index out of bounds.
       
   408 
       
   409 @see RSqlStatement::BindZeroBlob()
       
   410 */	
       
   411 TInt CSqlStatementImpl::BindZeroBlob(TInt aParamIndex, TInt aBlobSize)
       
   412 	{
       
   413 	__SQLASSERT_ALWAYS((TUint)aParamIndex < (TUint)iParamCnt, ESqlPanicBadColumnIndex);
       
   414 	iBound = EFalse;
       
   415 	iParamValBufIt.MoveTo(aParamIndex);
       
   416 	return iParamValBufIt.SetZeroBlob(aBlobSize);
       
   417 	}
       
   418 
       
   419 /**
       
   420 Implements RSqlStatement::ColumnType().
       
   421 
       
   422 @panic SqlDb 5 Column index out of bounds.
       
   423 @panic SqlDb 11 Statement cursor not positioned on a row.
       
   424 
       
   425 @see RSqlStatement::ColumnType().
       
   426 */	
       
   427 TSqlColumnType CSqlStatementImpl::ColumnType(TInt aColumnIndex)
       
   428 	{
       
   429 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   430 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   431 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   432 	return static_cast <TSqlColumnType> (iColumnValBufIt.Type());
       
   433 	}
       
   434 
       
   435 /**
       
   436 Implements RSqlStatement::DeclaredColumnType().
       
   437 
       
   438 @param aColumnIndex The index value identifying the column. This is 0 for the first column.
       
   439 @param aColumnType	Output parameter. Upon completion this will contain the type of the column.
       
   440 
       
   441 @return KErrNone, the operation completed successfully;
       
   442         KErrNoMemory, an out of memory condition has occurred.
       
   443                   One of the other system-wide error codes may also be returned.
       
   444 
       
   445 @panic SqlDb 5 Column index out of bounds.
       
   446 
       
   447 @see RSqlStatement::DeclaredColumnType().
       
   448 */
       
   449 TInt CSqlStatementImpl::DeclaredColumnType(TInt aColumnIndex, TSqlColumnType& aColumnType)
       
   450 	{
       
   451 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   452 	if(iDeclaredColumnTypes.Count() == 0 && iColumnCnt > 0) //initialise iDeclaredColumnTypes array if necessary
       
   453 		{
       
   454 		TInt err = iDeclaredColumnTypes.Reserve(iColumnCnt);//We know what the array size should be - iColumnCnt
       
   455 		if(err != KErrNone)
       
   456 			{
       
   457 			return err;
       
   458 			}
       
   459 		HBufC* colTypeNamesBuf = NULL;//Buffer for declared column type names, delimited by ';'.
       
   460 		TRAP(err, colTypeNamesBuf = GetDeclColumnTypesL());
       
   461 		if(err != KErrNone)
       
   462 			{
       
   463 			__SQLASSERT(!colTypeNamesBuf, ESqlPanicInternalError);
       
   464 			iDeclaredColumnTypes.Reset();
       
   465 			return err;	
       
   466 			}
       
   467 		//Iterate over the column type names and map each column type name to one of the TSqlColumnType enum item values.
       
   468 		//No error can occur from here till the end of the function code.
       
   469 		__SQLASSERT(colTypeNamesBuf != NULL, ESqlPanicInternalError);
       
   470 		TPtrC colTypeNames(*colTypeNamesBuf);
       
   471 		TInt colIdx = 0;
       
   472 		while(colTypeNames.Length() > 0)
       
   473 			{
       
   474 			TInt pos = colTypeNames.Find(KSemiColon);
       
   475 			if(pos < 0)
       
   476 				{
       
   477 				break;
       
   478 				}
       
   479 			TPtrC colTypeName(colTypeNames.Ptr(), pos);
       
   480 			if(pos == colTypeNames.Length() - 1)
       
   481 				{
       
   482 				colTypeNames.Set(NULL, 0);	
       
   483 				}
       
   484 			else
       
   485 				{
       
   486 				colTypeNames.Set(colTypeNames.Ptr() + pos + 1, colTypeNames.Length() - (pos + 1));
       
   487 				}
       
   488 			TSqlColumnType colType = ESqlInt;
       
   489 			if(colTypeName.FindF(KCharKWD) >= 0 || colTypeName.FindF(KTextKWD) >= 0 || colTypeName.FindF(KClobKWD) >= 0)
       
   490 				{
       
   491 				colType = ESqlText;
       
   492 				}
       
   493 			else if(colTypeName.FindF(KBinaryKWD) >= 0 || colTypeName.FindF(KBlobKWD) >= 0)
       
   494 				{
       
   495 				colType = ESqlBinary;
       
   496 				}
       
   497 			else if(colTypeName.FindF(KRealKWD) >= 0 || colTypeName.FindF(KFloatKWD) >= 0 || colTypeName.FindF(KDoubleKWD) >= 0)
       
   498 				{
       
   499 				colType = ESqlReal;
       
   500 				}
       
   501 			err = iDeclaredColumnTypes.Append(colType);
       
   502 			__SQLASSERT(err == KErrNone, ESqlPanicInternalError);//memory for the array elements has been reserved already
       
   503 			++colIdx;
       
   504 			}//end of - while(colTypeNames.Length() > 0)
       
   505 		__SQLASSERT(colIdx == iColumnCnt, ESqlPanicInternalError);
       
   506 		delete colTypeNamesBuf;
       
   507 		}//end of - if(iDeclaredColumnTypes.Count() == 0 && iColumnCnt > 0)
       
   508 	aColumnType = iDeclaredColumnTypes[aColumnIndex];
       
   509 	return KErrNone;
       
   510 	}
       
   511 	
       
   512 /**
       
   513 Implements RSqlStatement::ColumnSize().
       
   514 
       
   515 @panic SqlDb 5 Column index out of bounds.
       
   516 @panic SqlDb 11 Statement cursor not positioned on a row
       
   517 
       
   518 @see RSqlStatement::ColumnSize().
       
   519 */	
       
   520 TInt CSqlStatementImpl::ColumnSize(TInt aColumnIndex)
       
   521 	{
       
   522 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   523 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   524 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   525 	return iColumnValBufIt.Size();
       
   526 	}
       
   527 
       
   528 /**
       
   529 Implements RSqlStatement::ColumnInt().
       
   530 
       
   531 @panic SqlDb 5 Column index out of bounds.
       
   532 @panic SqlDb 11 Statement cursor not positioned on a row
       
   533 
       
   534 @see RSqlStatement::ColumnInt().
       
   535 */	
       
   536 TInt CSqlStatementImpl::ColumnInt(TInt aColumnIndex)
       
   537 	{
       
   538 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   539 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   540 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   541 	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
       
   542 	return iColumnValBufIt.Int();
       
   543 	}
       
   544 	
       
   545 /**
       
   546 Implements RSqlStatement::ColumnInt64().
       
   547 
       
   548 @panic SqlDb 5 Column index out of bounds.
       
   549 @panic SqlDb 11 Statement cursor not positioned on a row
       
   550 
       
   551 @see RSqlStatement::ColumnInt64().
       
   552 */	
       
   553 TInt64 CSqlStatementImpl::ColumnInt64(TInt aColumnIndex)
       
   554 	{
       
   555 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   556 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   557 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   558 	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
       
   559 	return iColumnValBufIt.Int64();
       
   560 	}
       
   561 	
       
   562 /**
       
   563 Implements RSqlStatement::ColumnReal().
       
   564 
       
   565 @panic SqlDb 5 Column index out of bounds.
       
   566 @panic SqlDb 11 Statement cursor not positioned on a row
       
   567 
       
   568 @see RSqlStatement::ColumnReal().
       
   569 */	
       
   570 TReal CSqlStatementImpl::ColumnReal(TInt aColumnIndex)
       
   571 	{
       
   572 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   573 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   574 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   575 	__SQLASSERT(iColumnValBufIt.IsPresent(), ESqlPanicValueNotPresent);
       
   576 	return iColumnValBufIt.Real();
       
   577 	}
       
   578 
       
   579 /**
       
   580 Return a text (16 bit) descriptor to a text column identified by aColumnIndex.
       
   581 
       
   582 @param aColumnIndex Column index
       
   583 @param aPtr An output parameter which will be set to point to the column data.
       
   584 
       
   585 @return KErrNone, if the function completes successfully,
       
   586                   otherwise one of the other system-wide error codes.
       
   587 
       
   588 @panic SqlDb 5 Column index out of bounds.
       
   589 @panic SqlDb 11 Statement cursor not positioned on a row
       
   590 */	
       
   591 TInt CSqlStatementImpl::ColumnText(TInt aColumnIndex, TPtrC& aPtr)
       
   592 	{
       
   593 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   594 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   595 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   596 	if(iColumnValBufIt.IsPresent())
       
   597 		{
       
   598 		aPtr.Set(iColumnValBufIt.Text());
       
   599 		return KErrNone;
       
   600 		}
       
   601 	//The text column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
       
   602 	//In this case an additional call to the server is made to get the column value.
       
   603 	//The column value is stored in a separate collection (iLongColumnColl), because if iColumnValueBuf gets reallocated,
       
   604 	//the client can get a dangling pointer to some of the located in iColumnValueBuf text/binary column values.
       
   605 	if(iColumnValBufIt.Type() != ESqlText)
       
   606 		{
       
   607 		aPtr.Set(KNullDesC);
       
   608 		return KErrNone;
       
   609 		}
       
   610 	if(!iLongColumnColl.IsPresent(aColumnIndex))
       
   611 		{
       
   612 		TSqlLongColumnReader colReader(iSqlStmtSession);
       
   613 		TInt err = iLongColumnColl.Append(colReader, aColumnIndex, iColumnValBufIt.Size() * sizeof(TUint16));
       
   614 		if(err != KErrNone)
       
   615 			{
       
   616 			return err;	
       
   617 			}
       
   618 		}
       
   619 	aPtr.Set(iLongColumnColl.Text(aColumnIndex));
       
   620 	return KErrNone;
       
   621 	}
       
   622 
       
   623 /**
       
   624 Copies the content of a text column, identified by aColumnIndex, to the place refered by aDest parameter.
       
   625 
       
   626 If the destination buffer is not big enough, the function will copy as much data as possible and will
       
   627 return KErrOverflow.
       
   628 
       
   629 @param aColumnIndex Column index
       
   630 @param aDest Refers to the place where the column data will be copied.
       
   631 
       
   632 @return KErrNone, if the function completes successfully,
       
   633                   otherwise one of the other system-wide error codes.
       
   634 
       
   635 @panic SqlDb 5 Column index out of bounds.
       
   636 @panic SqlDb 11 Statement cursor not positioned on a row
       
   637 */	
       
   638 TInt CSqlStatementImpl::ColumnText(TInt aColumnIndex, TDes& aDest)
       
   639 	{
       
   640 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   641 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   642 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   643 	TInt err = KErrNone;
       
   644 	//The text column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
       
   645 	//In this case an additional call to the server is made to get the column value.
       
   646 	if(!iColumnValBufIt.IsPresent())
       
   647 		{
       
   648 		if(iColumnValBufIt.Type() != ESqlText)
       
   649 			{
       
   650 			aDest.Zero();
       
   651 			return err;
       
   652 			}
       
   653 		TPtr8 ptr(reinterpret_cast <TUint8*> (const_cast <TUint16*> (aDest.Ptr())), aDest.MaxLength() * sizeof(TUint16));
       
   654 		err = iSqlStmtSession.ReadColumnValue(aColumnIndex, ptr);
       
   655 		if(err == KErrNone || err == KErrOverflow)
       
   656 			{
       
   657 			aDest.SetLength(ptr.Length() / sizeof(TUint16));
       
   658 			}
       
   659 		}
       
   660 	else
       
   661 		{
       
   662 		TPtrC src = iColumnValBufIt.Text();
       
   663 		TInt len = src.Length();
       
   664 		if(len > aDest.MaxLength())
       
   665 			{
       
   666 			len = aDest.MaxLength();
       
   667 			err = KErrOverflow;
       
   668 			}
       
   669 		aDest.Copy(src.Ptr(), len);
       
   670 		}
       
   671 	return err;
       
   672 	}
       
   673 
       
   674 /**
       
   675 Return a binary (8 bit) descriptor to a binary column identified by aColumnIndex.
       
   676 
       
   677 @param aColumnIndex Column index
       
   678 @param aPtr An output parameter which will be set to point to the column data.
       
   679 
       
   680 @return KErrNone, if the function completes successfully,
       
   681                   otherwise one of the other system-wide error codes.
       
   682 
       
   683 @panic SqlDb 5 Column index out of bounds.
       
   684 @panic SqlDb 11 Statement cursor not positioned on a row
       
   685 */	
       
   686 TInt CSqlStatementImpl::ColumnBinary(TInt aColumnIndex, TPtrC8& aPtr)
       
   687 	{
       
   688 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   689 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   690 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   691 	if(iColumnValBufIt.IsPresent())
       
   692 		{
       
   693 		aPtr.Set(iColumnValBufIt.Binary());
       
   694 		return KErrNone;
       
   695 		}
       
   696 	//The binary column value has not been transferred to the client side if its length is >= KSqlMaxDesLen characters.
       
   697 	//In this case an additional call to the server is made to get the column value.
       
   698 	//The column value is stored in a separate collection (iLongColumnColl), because if iColumnValueBuf gets reallocated,
       
   699 	//the client can get a dangling pointer to some of the located in iColumnValueBuf text/binary column values.
       
   700 	if(iColumnValBufIt.Type() != ESqlBinary)
       
   701 		{
       
   702 		aPtr.Set(KNullDesC8);
       
   703 		return KErrNone;
       
   704 		}
       
   705 	if(!iLongColumnColl.IsPresent(aColumnIndex))
       
   706 		{
       
   707 		TSqlLongColumnReader colReader(iSqlStmtSession);
       
   708 		TInt err = iLongColumnColl.Append(colReader, aColumnIndex, iColumnValBufIt.Size());
       
   709 		if(err != KErrNone)
       
   710 			{
       
   711 			return err;	
       
   712 			}
       
   713 		}
       
   714 	aPtr.Set(iLongColumnColl.Binary(aColumnIndex));
       
   715 	return KErrNone;
       
   716 	}
       
   717 
       
   718 /**
       
   719 Copies the content of a binary column, identified by aColumnIndex, to the place refered by aDest parameter.
       
   720 
       
   721 If the destination buffer is not big enough, the function will copy as much data as possible and will
       
   722 return KErrOverflow.
       
   723 
       
   724 @param aColumnIndex Column index
       
   725 @param aDest Refers to the place where the column data will be copied.
       
   726 
       
   727 @return KErrNone, if the function completes successfully,
       
   728                   otherwise one of the other system-wide error codes.
       
   729 
       
   730 @panic SqlDb 5 Column index out of bounds.
       
   731 @panic SqlDb 11 Statement cursor not positioned on a row
       
   732 */	
       
   733 TInt CSqlStatementImpl::ColumnBinary(TInt aColumnIndex, TDes8& aDest)
       
   734 	{
       
   735 	__SQLASSERT_ALWAYS((TUint)aColumnIndex < (TUint)iColumnCnt, ESqlPanicBadColumnIndex);
       
   736 	__SQLASSERT_ALWAYS(iState == CSqlStatementImpl::EAtRow, ESqlPanicInvalidRow);
       
   737 	iColumnValBufIt.MoveTo(aColumnIndex);		
       
   738 	TInt err = KErrNone;
       
   739 	//The binary column value has not been transferred to the client side if its length is >= KSqlMaxDesLen bytes.
       
   740 	//In this case an additional call to the server is made to get the column value.
       
   741 	if(!iColumnValBufIt.IsPresent())
       
   742 		{
       
   743 		if(iColumnValBufIt.Type() != ESqlBinary)
       
   744 			{
       
   745 			aDest.Zero();
       
   746 			return err;
       
   747 			}
       
   748 		err = iSqlStmtSession.ReadColumnValue(aColumnIndex, aDest);
       
   749 		}
       
   750 	else
       
   751 		{
       
   752 		TPtrC8 src = iColumnValBufIt.Binary();
       
   753 		TInt len = src.Length();
       
   754 		if(len > aDest.MaxLength())
       
   755 			{
       
   756 			len = aDest.MaxLength();
       
   757 			err = KErrOverflow;
       
   758 			}
       
   759 		aDest.Copy(src.Ptr(), len);
       
   760 		}
       
   761 	return err;
       
   762 	}
       
   763 
       
   764 /**
       
   765  * Obtain the name of a column after performing a query.
       
   766  * 
       
   767  * @param aColumnIndex Column index
       
   768  * @param aNameDest Descriptor which will be set to column name
       
   769  * @return KErrNone if successfull or one of the system-wide error codes on error
       
   770  */
       
   771 TInt CSqlStatementImpl::ColumnName(TInt aColumnIndex, TPtrC& aNameDest)
       
   772 	{
       
   773 	return Index2Name(aColumnIndex, iColumnNameBuf, iColumnCnt, ESqlSrvStmtColumnNames, iColumnNameBufPresent, aNameDest);
       
   774 	}
       
   775 
       
   776 /**
       
   777  * Obtain the name of a parameter after preparing a DML query.
       
   778  * 
       
   779  * @param aParamIndex Parameter index
       
   780  * @param aNameDest Descriptor which will be set to column name
       
   781  * @return KErrNone if successfull or one of the system-wide error codes on error
       
   782  */
       
   783 TInt CSqlStatementImpl::ParameterName(TInt aParamIndex, TPtrC& aNameDest)
       
   784 	{
       
   785 	return Index2Name(aParamIndex, iParamNameBuf, iParamCnt, ESqlSrvStmtParamNames, iParamNameBufPresent, aNameDest);
       
   786 	}
       
   787 
       
   788 
       
   789 TInt CSqlStatementImpl::Name2Index(const TDesC& aName, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent)
       
   790 	{
       
   791 	if(aCount == 0)
       
   792 		{
       
   793 		return KErrNotFound;	
       
   794 		}
       
   795 	TInt err = CheckNameBufPresent(aPresent, aNameBufFlat, aCount, aFunction);
       
   796 	if ( err != KErrNone ) 
       
   797 		{
       
   798 		return err;
       
   799 		}
       
   800 	TInt idx = -1;
       
   801 	aPresent = ETrue;	
       
   802 	TSqlBufRIterator nameBufIt;
       
   803 	nameBufIt.Set(aNameBufFlat);
       
   804 	while(nameBufIt.Next())
       
   805 		{
       
   806 		++idx;
       
   807 		if(::CompareNoCase16(aName, nameBufIt.Text()) == 0)
       
   808 			{
       
   809 			return idx;	
       
   810 			}
       
   811 		}
       
   812 	return KErrNotFound;
       
   813 	}
       
   814 
       
   815                    
       
   816 TInt CSqlStatementImpl::Index2Name(TInt aIndex, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent, TPtrC& aColName)
       
   817 	{
       
   818 	if( aCount == 0 || aIndex < 0 || aIndex >= aCount ) 
       
   819 		{
       
   820 		return KErrNotFound;	
       
   821 		}
       
   822 	TInt err = CheckNameBufPresent(aPresent, aNameBufFlat, aCount, aFunction);
       
   823 	if ( err != KErrNone ) 
       
   824 		{
       
   825 		return err;
       
   826 		}
       
   827 	aPresent = ETrue;	
       
   828 	TSqlBufRIterator nameBufIt;
       
   829 	nameBufIt.Set(aNameBufFlat);
       
   830 	nameBufIt.MoveTo(aIndex);
       
   831 	aColName.Set(nameBufIt.Text());
       
   832 	return KErrNone;
       
   833 	}
       
   834 
       
   835 /**
       
   836 Ensures that the specified names buffer is present on the client side.
       
   837 Name buffers are used for transporting parameter and column names.
       
   838 
       
   839 @return KErrNone if successfull or one of the system-wide error codes on error
       
   840 @internalComponent
       
   841 */
       
   842 TInt CSqlStatementImpl::CheckNameBufPresent(TBool& aPresent, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction)
       
   843 	{
       
   844 	if(!aPresent)
       
   845 		{
       
   846 		aNameBufFlat.Close();
       
   847 		TInt err = aNameBufFlat.SetCount(aCount);
       
   848 		if(err != KErrNone)
       
   849 			{
       
   850 			return err;	
       
   851 			}
       
   852 		err = iSqlStmtSession.GetNames(aFunction, aNameBufFlat);
       
   853 		if(err != KErrNone)
       
   854 			{
       
   855 			return err;	
       
   856 			}
       
   857 		}
       
   858 	return KErrNone;
       
   859 	}
       
   860 
       
   861 
       
   862 /**
       
   863 Returns a buffer containing a ";" separated list with declared types of statement's columns.
       
   864 The caller is responsible for deleting the result buffer.
       
   865 
       
   866 @return HBufC buffer - column types list.
       
   867 */
       
   868 HBufC* CSqlStatementImpl::GetDeclColumnTypesL()
       
   869 	{
       
   870 	return iSqlStmtSession.GetDeclColumnTypesL(iColumnCnt);
       
   871 	}
       
   872