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. |
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 |