persistentstorage/sql/SRC/Server/SqlSrvStatement.cpp
changeset 17 55f2396f6d25
parent 0 08ec8eefde2f
child 22 a7ba600cb39d
equal deleted inserted replaced
15:3eacc0623088 17:55f2396f6d25
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     7 //
     8 // Initial Contributors:
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
     9 // Nokia Corporation - initial contribution.
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
       
    12 // NTT DOCOMO, INC - Fix for defect 1915 "SQL server panics when using long column type strings"
    12 //
    13 //
    13 // Description:
    14 // Description:
    14 //
    15 //
    15 
    16 
    16 #include <utf.h>					//CnvUtfConverter
    17 #include <utf.h>					//CnvUtfConverter
    26 //////////////////////////////////////////////////////////////////////////////////////////////////////
    27 //////////////////////////////////////////////////////////////////////////////////////////////////////
    27 
    28 
    28 //This is the name prefix which will be given to the nameless parameters.
    29 //This is the name prefix which will be given to the nameless parameters.
    29 //For example, if the SQL string is:
    30 //For example, if the SQL string is:
    30 //   SELECT * FROM A WHERE ColA1 = ? AND ColA2 = ?
    31 //   SELECT * FROM A WHERE ColA1 = ? AND ColA2 = ?
    31 //then the names which will be give to the parameters will be:
    32 //then the names which will be given to the parameters will be:
    32 //"?0" and "?1"
    33 //"?0" and "?1"
    33 _LIT(KNamelessParameter, "?");
    34 _LIT(KNamelessParameter, "?");
    34 
    35 
    35 
    36 
    36 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    37 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    88 /**
    89 /**
    89 This function is called by the bound statement object to notify the current HSqlSrvStmtParamBuf object that the
    90 This function is called by the bound statement object to notify the current HSqlSrvStmtParamBuf object that the
    90 bound statement is about to be finalized. That means, when the "stream close" operation on the client side 
    91 bound statement is about to be finalized. That means, when the "stream close" operation on the client side 
    91 makes an attempt to synch the HSqlSrvStmtParamBuf object, no attempt should be made to bound the parameter data,
    92 makes an attempt to synch the HSqlSrvStmtParamBuf object, no attempt should be made to bound the parameter data,
    92 because the statement object is gone.
    93 because the statement object is gone.
    93 After this call the bound statement objects seases to exist.
    94 After this call the bound statement objects ceases to exist.
    94 
    95 
    95 Actions, performed by this method:
    96 Actions, performed by this method:
    96  - if the buffer type is "simple bind", the buffer will be destroyed. No reason to keep it alive, there is no bound IPC
    97  - if the buffer type is "simple bind", the buffer will be destroyed. No reason to keep it alive, there is no bound IPC
    97    stream object on the client side;
    98    stream object on the client side;
    98  - if the buffer type is an IPC stream buffer and the buffer is alive, that means: the bound statement object is about to be
    99  - if the buffer type is an IPC stream buffer and the buffer is alive, that means: the bound statement object is about to be
   198 	}
   199 	}
   199 
   200 
   200 /**
   201 /**
   201 Sets SQL statement parameter values.
   202 Sets SQL statement parameter values.
   202 
   203 
   203 Only parameters, which values are set by the client, will be processed.
   204 Only parameters, whose values are set by the client, will be processed.
   204 
   205 
   205 @param aParamBuf Flat buffer with parameter values.
   206 @param aParamBuf Flat buffer with parameter values.
   206 
   207 
   207 @leave KErrArgument, unknown parameter type;
   208 @leave KErrArgument, unknown parameter type;
   208 	   KSqlErrStmtExpired, statement handle expired.
   209 	   KSqlErrStmtExpired, statement handle expired.
   275 	}
   276 	}
   276 
   277 
   277 /**
   278 /**
   278 Collects column names in a flat buffer and returns a reference to the buffer. 
   279 Collects column names in a flat buffer and returns a reference to the buffer. 
   279 
   280 
   280 @return A const reference to a flat buffer containing the column values.
   281 @return A const reference to a flat buffer containing the column names.
   281 
   282 
   282 @leave KErrNoMemory, an out of memory condition has occurred.
   283 @leave KErrNoMemory, an out of memory condition has occurred.
   283 
   284 
   284 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   285 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   285 */	
   286 */	
   304 	}
   305 	}
   305 
   306 
   306 /**
   307 /**
   307 Collects parameter names in a flat buffer and returns a reference to the buffer. 
   308 Collects parameter names in a flat buffer and returns a reference to the buffer. 
   308 
   309 
   309 @return A const reference to a flat buffer containing the column values.
   310 @return A const reference to a flat buffer containing the parameter names.
   310 
   311 
   311 @leave KErrNoMemory, an out of memory condition has occurred.
   312 @leave KErrNoMemory, an out of memory condition has occurred.
   312 
   313 
   313 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   314 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   314 */	
   315 */	
   380 				__SQLLEAVE_IF_ERROR(it.SetReal(sqlite3_column_double(iStmtHandle, colIdx)));
   381 				__SQLLEAVE_IF_ERROR(it.SetReal(sqlite3_column_double(iStmtHandle, colIdx)));
   381 				break;
   382 				break;
   382 			case SQLITE_TEXT:
   383 			case SQLITE_TEXT:
   383 				{
   384 				{
   384 				TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, colIdx) / sizeof(TUint16);
   385 				TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, colIdx) / sizeof(TUint16);
       
   386                 //"charLength == 0" - this might be an indication of an "out of memory" problem, if the column text is in UTF8 format. 
       
   387                 //(sqlite3_column_bytes16() may allocate memory for UTF8->UTF16 conversion)
       
   388 				if(charLength == 0 && sqlite3_errcode(sqlite3_db_handle(iStmtHandle)) == SQLITE_NOMEM)
       
   389                     {
       
   390                     __SQLLEAVE(KErrNoMemory);
       
   391                     }
   385 				if(charLength >= KSqlMaxDesLen)
   392 				if(charLength >= KSqlMaxDesLen)
   386 					{
   393 					{
   387 					it.SetAsNotPresent(ESqlText, charLength);
   394 					it.SetAsNotPresent(ESqlText, charLength);
   388 					}
   395 					}
   389 				else
   396 				else
   390 					{
   397 					{//sqlite3_column_bytes16() already allocated the needed memory if a UTF8->UTF16 conversion
   391 					__SQLLEAVE_IF_ERROR(it.SetText(TPtrC16(reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, colIdx)), charLength)));
   398                      //had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
       
   399 					const TUint16* text = reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, colIdx));
       
   400 					__SQLASSERT(text != NULL, ESqlPanicInternalError);
       
   401 					__SQLLEAVE_IF_ERROR(it.SetText(TPtrC16(text, charLength)));
   392 					}
   402 					}
   393 				}
   403 				}
   394 				break;
   404 				break;
   395 			case SQLITE_BLOB:
   405 			case SQLITE_BLOB:
   396 				{
   406 				{
   432 TInt CSqlSrvStatement::ColumnSource(TInt aColumnIndex, TPtrC8& aColumnSource) const
   442 TInt CSqlSrvStatement::ColumnSource(TInt aColumnIndex, TPtrC8& aColumnSource) const
   433 	{
   443 	{
   434 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   444 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   435 	TInt colType = sqlite3_column_type(iStmtHandle, aColumnIndex);
   445 	TInt colType = sqlite3_column_type(iStmtHandle, aColumnIndex);
   436 	if(colType == SQLITE_TEXT)
   446 	if(colType == SQLITE_TEXT)
   437 		{
   447         {//Since the first called function after the Next() operation is always CSqlSrvStatement::ColumnValuesL(), then
       
   448          //sqlite3_column_bytes16() (called from  ColumnValuesL()) already allocated the needed memory if a UTF8->UTF16 
       
   449          //conversion had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
   438 		const void* text = sqlite3_column_text16(iStmtHandle, aColumnIndex);
   450 		const void* text = sqlite3_column_text16(iStmtHandle, aColumnIndex);
       
   451         __SQLASSERT(text != NULL, ESqlPanicInternalError);
   439 		TInt length  = sqlite3_column_bytes16(iStmtHandle, aColumnIndex);
   452 		TInt length  = sqlite3_column_bytes16(iStmtHandle, aColumnIndex);
   440 		aColumnSource.Set(reinterpret_cast <const TUint8*> (text), length);
   453 		aColumnSource.Set(reinterpret_cast <const TUint8*> (text), length);
   441 		}
   454 		}
   442 	else if(colType == SQLITE_BLOB)
   455 	else if(colType == SQLITE_BLOB)
   443 		{
   456 		{
   643 the function will do a data conversion as described in the table which can be found
   656 the function will do a data conversion as described in the table which can be found
   644 in SqlDb.h file.
   657 in SqlDb.h file.
   645 		
   658 		
   646 @see RSqlStatement
   659 @see RSqlStatement
   647 
   660 
       
   661 @leave KErrNoMemory, an out of memory condition has occurred.
       
   662 
   648 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   663 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   649 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
   664 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
   650 */
   665 */
   651 TPtrC CSqlSrvStatement::ColumnText(TInt aColIdx) const
   666 TPtrC CSqlSrvStatement::ColumnTextL(TInt aColIdx) const
   652 	{
   667 	{
   653 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   668 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   654 	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
   669 	__SQLASSERT((TUint)aColIdx < iColumnCount, ESqlPanicBadArgument);
   655 	TPtrC res;
   670 	TPtrC res;
   656 	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
   671 	TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
   657 	if(colType == SQLITE_TEXT)
   672 	if(colType == SQLITE_TEXT)
   658 		{
   673 		{
   659 		TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, aColIdx) / sizeof(TUint16);
   674 		TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, aColIdx) / sizeof(TUint16);
   660 		res.Set(reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, aColIdx)), charLength);
   675         //"charLength == 0" - this might be an indication of an "out of memory" problem, if the column text is in UTF8 format. 
       
   676         //(sqlite3_column_bytes16() may allocate memory for UTF8->UTF16 conversion)
       
   677         if(charLength == 0 && sqlite3_errcode(sqlite3_db_handle(iStmtHandle)) == SQLITE_NOMEM)
       
   678             {
       
   679             __SQLLEAVE(KErrNoMemory);
       
   680             }
       
   681         //sqlite3_column_bytes16() already allocated the needed memory if a UTF8->UTF16 conversion
       
   682         //had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
       
   683         const TUint16* text = reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, aColIdx));
       
   684         __SQLASSERT(text != NULL, ESqlPanicInternalError);
       
   685 		res.Set(text, charLength);
   661 		}
   686 		}
   662 	return res;
   687 	return res;
   663 	}
   688 	}
   664 	
   689 	
   665 /**
   690 /**
   686 		}
   711 		}
   687 	return res;
   712 	return res;
   688 	}
   713 	}
   689 
   714 
   690 /**
   715 /**
   691 This function is used by the DBMS emulation library only.
   716 Retrieves the declared column types using the SQLITE library storing in a 
   692 The function retrieves the declared column types from the SQLITE library, compiles them in a single string
   717 flat buffer and returns a reference to the buffer. 
   693 and then returns the string to the caller.
   718 
   694 
   719 @return A const reference to a flat buffer containing the declared column type names.
   695 The function also initializes iColumnText8 array, where particular array element with index "idx" will 
   720 
   696 be set to 1, if the column with index "idx" is a 8-bit text column.
   721 @leave KErrNoMemory, an out of memory condition has occurred;
   697 
   722 
   698 @return A pointer to a heap allocated HBufC object with the delcared column types. The caller is responsible
   723 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   699 		for the HBufC object destruction.
   724 */
   700 */
   725 const RSqlBufFlat& CSqlSrvStatement::GetDeclColumnTypesL()
   701 HBufC* CSqlSrvStatement::GetDeclColumnTypesL()
   726 	{
   702 	{
   727 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   703 	HBufC* buf = HBufC::NewL(iColumnCount * 20);//20 as length is enough for a single column type text
   728 	iBufFlatType = static_cast <TSqlBufFlatType> (-1);
   704 	TPtr ptr = buf->Des();
   729 	__SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iColumnCount));
   705 	for(TInt i=0;i<iColumnCount;++i)
   730 	TSqlBufWIterator it;
   706 		{
   731 	it.Set(iBufFlat);
   707 		const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, i));
   732 	TInt colIdx = -1;
   708 		if(declTypeTxt)
   733 	while(it.Next())
   709 			{
   734 		{
   710 			TPtrC type(declTypeTxt, User::StringLength(declTypeTxt));
   735 		++colIdx;//the first SQLITE column index is 0
   711 			ptr.Append(type);
   736 		const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, colIdx));
   712 			}
   737 		TPtrC ptr(KNullDesC);
   713 		ptr.Append(TChar(';'));
   738         if(declTypeTxt)
   714 		}
   739             {
   715 	return buf;
   740             ptr.Set(declTypeTxt, User::StringLength(declTypeTxt));
   716 	}
   741             }
   717 
   742         else
   718 /**
   743             {
   719 Creates a new HSqlSrvStmtParamBuf object.
   744             //If sqlite3_column_decltype16() returns NULL but sqlite3_column_decltype() doesn't, then it is an "out of memory" condition 
   720 
   745             if(sqlite3_column_decltype(iStmtHandle, colIdx))
   721 @param aParameterIndex Parameter index, zero based.
   746                 {
       
   747                 __SQLLEAVE(KErrNoMemory);
       
   748                 }
       
   749             }
       
   750 		__SQLLEAVE_IF_ERROR(it.SetText(ptr));
       
   751 		}
       
   752 	iBufFlatType = ESqlDeclColumnTypesBuf;
       
   753 	return iBufFlat;	
       
   754 	}
       
   755 
       
   756 
       
   757 /**
       
   758 Creates a new HSqlSrvStmtParamBuf object for the parameter with index "aParamIndex" or
       
   759 reuses the existing one.
       
   760 
       
   761 @param aParamIndex Parameter index, zero based.
   722 @param aDataType Parameter value type - binary, text8 or text16.
   762 @param aDataType Parameter value type - binary, text8 or text16.
   723 @param aIsStreamBuf True if the param data will be retrieved from an IPC stream
   763 @param aIsStreamBuf True if the param data will be retrieved from an IPC stream
   724 
   764 
   725 @return A pointer to the created HSqlSrvStmtParamBuf instance.
   765 @return A pointer to the created HSqlSrvStmtParamBuf instance.
   726 
   766 
   744 	return paramBuf;
   784 	return paramBuf;
   745 	}
   785 	}
   746 
   786 
   747 /**
   787 /**
   748 This function will extend the iParamBufArray array (filling the new array items with NULL), if it is needed - 
   788 This function will extend the iParamBufArray array (filling the new array items with NULL), if it is needed - 
   749 to ensure that there is enough place for the buffer for the parameter identified by aParamIndex.
   789 to ensure that there is enough place in the buffer for the parameter identified by aParamIndex.
   750 
   790 
   751 @param aParamIndex The parameter index
   791 @param aParamIndex The parameter index
   752 
   792 
   753 @leave KErrNoMemory, an out of memory condition has occurred;
   793 @leave KErrNoMemory, an out of memory condition has occurred;
   754 
   794