persistentstorage/sql/SRC/Server/SqlSrvStatement.cpp
branchRCL_3
changeset 11 211563e4b919
parent 9 667e88a979d7
child 15 fcc16690f446
equal deleted inserted replaced
10:31a8f755b7fe 11:211563e4b919
     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 Bug 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
   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 @return A pointer to a heap allocated HBufC object with the delcared column types. The caller is responsible
   720 
   696 		for the HBufC object destruction.
   721 @leave KErrNoMemory, an out of memory condition has occurred;
   697 */
   722 
   698 HBufC* CSqlSrvStatement::GetDeclColumnTypesL()
   723 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
   699 	{
   724 */
   700 	HBufC* buf = HBufC::NewL(iColumnCount * 20);//20 as length is enough for a single column type text
   725 const RSqlBufFlat& CSqlSrvStatement::GetDeclColumnTypesL()
   701 	TPtr ptr = buf->Des();
   726 	{
   702 	for(TInt i=0;i<iColumnCount;++i)
   727 	__SQLASSERT(iStmtHandle != NULL, ESqlPanicInvalidObj);
   703 		{
   728 	iBufFlatType = static_cast <TSqlBufFlatType> (-1);
   704 		const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, i));
   729 	__SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iColumnCount));
   705 		if(declTypeTxt)
   730 	TSqlBufWIterator it;
   706 			{
   731 	it.Set(iBufFlat);
   707 			TPtrC type(declTypeTxt, User::StringLength(declTypeTxt));
   732 	TInt colIdx = -1;
   708 			ptr.Append(type);
   733 	while(it.Next())
   709 			}
   734 		{
   710 		ptr.Append(TChar(';'));
   735 		++colIdx;//the first SQLITE column index is 0
   711 		}
   736 		const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, colIdx));
   712 	return buf;
   737 		TPtrC ptr(KNullDesC);
   713 	}
   738         if(declTypeTxt)
       
   739             {
       
   740             ptr.Set(declTypeTxt, User::StringLength(declTypeTxt));
       
   741             }
       
   742         else
       
   743             {
       
   744             //If sqlite3_column_decltype16() returns NULL but sqlite3_column_decltype() doesn't, then it is an "out of memory" condition 
       
   745             if(sqlite3_column_decltype(iStmtHandle, colIdx))
       
   746                 {
       
   747                 __SQLLEAVE(KErrNoMemory);
       
   748                 }
       
   749             }
       
   750 		__SQLLEAVE_IF_ERROR(it.SetText(ptr));
       
   751 		}
       
   752 	iBufFlatType = ESqlDeclColumnTypesBuf;
       
   753 	return iBufFlat;	
       
   754 	}
       
   755 
   714 
   756 
   715 /**
   757 /**
   716 Creates a new HSqlSrvStmtParamBuf object for the parameter with index "aParamIndex" or
   758 Creates a new HSqlSrvStmtParamBuf object for the parameter with index "aParamIndex" or
   717 reuses the existing one.
   759 reuses the existing one.
   718 
   760