First public contribution.
1 // Copyright (c) 2005-2010 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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
12 // NTT DOCOMO, INC - Fix for defect 1915 "SQL server panics when using long column type strings"
17 #include <utf.h> //CnvUtfConverter
19 #include "SqliteSymbian.h" //sqlite3SymbianLastOsError()
21 #include "SqlSrvStatement.h"
22 #include "SqlBufIterator.h" //TSqlBufRIterator
23 #include "SqlSrvResourceProfiler.h"
24 #include "OstTraceDefinitions.h"
25 #ifdef OST_TRACE_COMPILER_IN_USE
26 #include "SqlSrvStatementTraces.h"
28 #include "SqlTraceDef.h"
30 //////////////////////////////////////////////////////////////////////////////////////////////////////
31 ///////////////////////////// local const data ////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////////////////////////////
34 //This is the name prefix which will be given to the nameless parameters.
35 //For example, if the SQL string is:
36 // SELECT * FROM A WHERE ColA1 = ? AND ColA2 = ?
37 //then the names which will be given to the parameters will be:
39 _LIT(KNamelessParameter, "?");
42 /////////////////////////////////////////////////////////////////////////////////////////////////////////
43 ////////////////// HSqlSrvStmtParamBuf //////////////////////////////////
44 /////////////////////////////////////////////////////////////////////////////////////////////////////////
47 Destroys the parameter buffer.
51 HSqlSrvStmtParamBuf::~HSqlSrvStmtParamBuf()
57 Binds the parameter value.
58 The buffer can be synch-ed if:
59 - this is the first synch operation;
60 - the bound statement object is still alive (not finalized);
61 - the current object is alive;
62 - the current object data is retrieved from an IPC stream;
64 If none of the conditions above is true, the synch operation is no-op.
68 void HSqlSrvStmtParamBuf::DoSynchL()
70 TBool dontSynch = iSynchDone || !iAlive || iStatementFinalized || iBufType != HSqlSrvStmtParamBuf::EBufIpcStream;
77 iStatement.BindParamBufL(iParamIndex);
81 Destroys the HSqlSrvStmtParamBuf instance.
82 This method is a no-op if the statement is not finalized yet.
86 void HSqlSrvStmtParamBuf::DoRelease()
89 if(iStatementFinalized)
90 {//The bound statement has been finalized - destroy the current object then.
96 This function is called by the bound statement object to notify the current HSqlSrvStmtParamBuf object that the
97 bound statement is about to be finalized. That means, when the "stream close" operation on the client side
98 makes an attempt to synch the HSqlSrvStmtParamBuf object, no attempt should be made to bound the parameter data,
99 because the statement object is gone.
100 After this call the bound statement objects ceases to exist.
102 Actions, performed by this method:
103 - if the buffer type is "simple bind", the buffer will be destroyed. No reason to keep it alive, there is no bound IPC
104 stream object on the client side;
105 - if the buffer type is an IPC stream buffer and the buffer is alive, that means: the bound statement object is about to be
106 finalized, but there is a bound client side IPC stream object that is still alive. In this case the buffer won't be destroyed,
107 but will be "told" that the bound statement is finalized, so when the client side IPC stream is closed, this object will get destroyed;
108 - 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
109 side and it is safe to destroy the buffer;
112 void HSqlSrvStmtParamBuf::NotifyStatementFinalized()
114 iStatementFinalized = ETrue;
115 if(iBufType == HSqlSrvStmtParamBuf::EBufSimpleBind || !iAlive)
121 //////////////////////////////////////////////////////////////////////////////////////////////////////
122 ///////////////////////////// CSqlSrvStatement class ////////////////////////////////////////////
123 //////////////////////////////////////////////////////////////////////////////////////////////////////
126 Creates a new CSqlSrvStatement instance.
128 The created CSqlSrvStatement instance will be placed in the cleanup stack.
130 @param aDbHandle The database handle
131 @param aSqlStmt 16-bit SQL statement, zero-terminated string
132 @param aColumnCount Output parameter. It will be initialized with the column count.
133 @param aParamCount Output parameter. It will be initialized with the parameter count.
135 @return A pointer to the created CSqlSrvStatement instance.
137 @leave KErrNoMemory, an out of memory condition has occurred;
138 KErrArgument, bad argument, for example - the SQL string contains more than one SQL statements.
139 Note that the function may also leave with some other database specific
140 errors categorised as ESqlDbError.
142 @panic SqlDb 4 In _DEBUG mode if aSqlStmt is not zero-terminated string.
144 CSqlSrvStatement* CSqlSrvStatement::NewLC(sqlite3* aDbHandle, const TDesC16& aSqlStmt, TInt& aColumnCount, TInt& aParamCount)
146 __SQLTRACE_INTERNALSEXPR(TPtrC sqlprnptr(aSqlStmt.Left(aSqlStmt.Length() - 1)));
147 SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVSTATEMENT_NEWLC_ENTRY, "Entry;0;CSqlSrvStatement::NewLC-16;aDbHandle=0x%X;aSqlStmt=%S", (TUint)aDbHandle, __SQLPRNSTR(sqlprnptr)));
148 __ASSERT_DEBUG(aSqlStmt.Length() > 0 ? (TInt)aSqlStmt[aSqlStmt.Length() - 1] == 0 : ETrue, __SQLPANIC2(ESqlPanicBadArgument));
150 CSqlSrvStatement* self = new (ELeave) CSqlSrvStatement;
151 CleanupStack::PushL(self);
152 self->ConstructL(aDbHandle, aSqlStmt);
153 aColumnCount = self->iColumnCount;
154 aParamCount = self->iParamCount;
155 SQL_TRACE_INTERNALS(OstTraceExt4(TRACE_INTERNALS, CSQLSRVSTATEMENT_NEWLC_EXIT, "Exit;0x%X;CSqlSrvStatement::NewLC-16;iStmtHandle=0x%X;aColumnCount=%d;aParamCount=%d", (TUint)self, (TUint)self->iStmtHandle, aColumnCount, aParamCount));
160 Creates a new CSqlSrvStatement instance.
162 The created CSqlSrvStatement instance will be placed in the cleanup stack.
164 @param aDbHandle The database handle
165 @param aSqlStmt 8-bit SQL statement, zero-terminated string
166 @param aColumnCount Output parameter. It will be initialized with the column count.
167 @param aParamCount Output parameter. It will be initialized with the parameter count.
169 @return A pointer to the created CSqlSrvStatement instance.
171 @leave KErrNoMemory, an out of memory condition has occurred;
172 KErrArgument, bad argument, for example - the SQL string contains more than one SQL statements.
173 Note that the function may also leave with some other database specific
174 errors categorised as ESqlDbError.
176 @panic SqlDb 4 In _DEBUG mode if aSqlStmt is not zero-terminated string.
178 CSqlSrvStatement* CSqlSrvStatement::NewLC(sqlite3* aDbHandle, const TDesC8& aSqlStmt, TInt& aColumnCount, TInt& aParamCount)
180 __SQLTRACE_INTERNALSEXPR(TPtrC8 sqlprnptr(aSqlStmt.Left(aSqlStmt.Length() - 1)));
181 __SQLTRACE_INTERNALSVAR(TBuf<100> des16prnbuf);
182 SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVSTATEMENT_NEWLC_ENTRY2, "Entry;0;CSqlSrvStatement::NewLC-8;aDbHandle=0x%X;aSqlStmt=%s", (TUint)aDbHandle, __SQLPRNSTR8(sqlprnptr, des16prnbuf)));
183 __ASSERT_DEBUG(aSqlStmt.Length() > 0 ? (TInt)aSqlStmt[aSqlStmt.Length() - 1] == 0 : ETrue, __SQLPANIC2(ESqlPanicBadArgument));
185 CSqlSrvStatement* self = new (ELeave) CSqlSrvStatement;
186 CleanupStack::PushL(self);
187 self->ConstructL(aDbHandle, aSqlStmt);
188 aColumnCount = self->iColumnCount;
189 aParamCount = self->iParamCount;
190 SQL_TRACE_INTERNALS(OstTraceExt4(TRACE_INTERNALS, CSQLSRVSTATEMENT_NEWLC_EXIT2, "Exit;0x%X;CSqlSrvStatement::NewLC-8;iStmtHandle=0x%X;aColumnCount=%d;aParamCount=%d", (TUint)self, (TUint)self->iStmtHandle, aColumnCount, aParamCount));
195 Destroys the allocated by CSqlSrvStatement instance memory and other resources.
197 CSqlSrvStatement::~CSqlSrvStatement()
199 SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVSTATEMENT_CSQLSRVSTATEMENT2_ENTRY, "Entry;0x%X;CSqlSrvStatement::~CSqlSrvStatement;iStmtHandle=0x%X", (TUint)this, (TUint)iStmtHandle));
200 DestroyParamBufArray();
204 #ifdef SYMBIAN_USE_SQLITE_VERSION_3_6_4
205 __SQLTRACE_INTERNALSEXPR(TInt scanCount = sqlite3_stmt_status(iStmtHandle, SQLITE_STMTSTATUS_FULLSCAN_STEP, ETrue));
206 __SQLTRACE_INTERNALSEXPR(TInt sortCount = sqlite3_stmt_status(iStmtHandle, SQLITE_STMTSTATUS_SORT, ETrue));
207 SQL_TRACE_INTERNALS(OstTraceExt3(TRACE_INTERNALS, CSQLSRVSTATEMENT_CSQLSRVSTATEMENT2, "0x%X;CSqlSrvStatement::~CSqlSrvStatement;scan count=%d;sort count=%d", (TUint)this, scanCount, sortCount));
209 (void)sqlite3_finalize(iStmtHandle);
211 SQL_TRACE_INTERNALS(OstTrace1(TRACE_INTERNALS, CSQLSRVSTATEMENT_CSQLSRVSTATEMENT2_EXIT, "Exit;0x%X;CSqlSrvStatement::~CSqlSrvStatement", (TUint)this));
215 Sets SQL statement parameter values.
217 Only parameters, whose values are set by the client, will be processed.
219 @param aParamBuf Flat buffer with parameter values.
221 @leave KErrArgument, unknown parameter type;
222 KSqlErrStmtExpired, statement handle expired.
223 Note that the function may also leave with some other database specific
224 errors categorised as ESqlDbError.
226 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
228 void CSqlSrvStatement::BindL(const RSqlBufFlat& aParamBuf)
230 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
232 (void)sqlite3SymbianLastOsError();//clear last OS error
238 TInt err = SQLITE_OK;
239 while(it.Next() && err == SQLITE_OK)
241 ++prmIdx;//the first SQLITE parameter index is 1
247 err = sqlite3_bind_int(iStmtHandle, prmIdx, it.Int());
250 err = sqlite3_bind_int64(iStmtHandle, prmIdx, it.Int64());
253 err = sqlite3_bind_double(iStmtHandle, prmIdx, it.Real());
256 //SQLITE_STATIC is used as an argument, because the text data will be kept and can be used by the next bind call
258 TPtrC text = it.Text();
259 TPtrC8 prmDataCopy(reinterpret_cast <const TUint8*> (text.Ptr()), text.Length() * sizeof(TUint16));
260 prmDataCopy.Set(CopyAndStoreParamL(prmIdx - 1, HSqlSrvStmtParamBuf::EText16, prmDataCopy));
261 err = sqlite3_bind_text16(iStmtHandle, prmIdx, prmDataCopy.Ptr(), prmDataCopy.Length(), SQLITE_STATIC);
265 //SQLITE_STATIC is used as an argument, because the blob data will be kept and can be used by the next bind call
267 TPtrC8 prmDataCopy = CopyAndStoreParamL(prmIdx - 1, HSqlSrvStmtParamBuf::EBinary, it.Binary());
268 err = sqlite3_bind_blob(iStmtHandle, prmIdx, prmDataCopy.Ptr(), prmDataCopy.Length(), SQLITE_STATIC);
272 err = sqlite3_bind_null(iStmtHandle, prmIdx);
275 err = sqlite3_bind_zeroblob(iStmtHandle, prmIdx, it.Int());
278 __SQLLEAVE(KErrArgument);//unknown parameter type
281 }//end of - if(it.IsPresent())
282 }//end of - while(it.Next() && err == SQLITE_OK)
283 err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
284 __SQLLEAVE_IF_ERROR(err);
288 Collects column names in a flat buffer and returns a reference to the buffer.
290 @return A const reference to a flat buffer containing the column names.
292 @leave KErrNoMemory, an out of memory condition has occurred.
294 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
296 const RSqlBufFlat& CSqlSrvStatement::ColumnNamesL()
298 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
299 iBufFlatType = static_cast <TSqlBufFlatType> (-1);
300 __SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iColumnCount));
306 ++colIdx;//the first SQLITE column index is 0
307 const TUint16* name = reinterpret_cast <const TUint16*> (__SQLLEAVE_IF_NULL(const_cast <void*> (sqlite3_column_name16(iStmtHandle, colIdx))));
308 TPtrC ptr(name, User::StringLength(name));
309 __SQLLEAVE_IF_ERROR(it.SetText(ptr));
311 iBufFlatType = ESqlColumnNamesBuf;
312 SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
317 Collects parameter names in a flat buffer and returns a reference to the buffer.
319 @return A const reference to a flat buffer containing the parameter names.
321 @leave KErrNoMemory, an out of memory condition has occurred.
323 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
325 const RSqlBufFlat& CSqlSrvStatement::ParamNamesL()
327 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
328 iBufFlatType = static_cast <TSqlBufFlatType> (-1);
329 __SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iParamCount));
335 ++prmIdx;//the first SQLITE parameter index is 1
336 const TUint8* name8 = reinterpret_cast <const TUint8*> (sqlite3_bind_parameter_name(iStmtHandle, prmIdx));
339 HBufC* name = CnvUtfConverter::ConvertToUnicodeFromUtf8L(TPtrC8(name8, User::StringLength(name8)));
340 TInt err = it.SetText(name->Des());
342 __SQLLEAVE_IF_ERROR(err);
344 else //nameless parameter case
346 //The parameter name in this case will be formatted as "?<num>", where <num> is the parameter index.
348 prmName.Append(KNamelessParameter);
349 prmName.AppendNum((TInt64)(prmIdx - 1));
350 __SQLLEAVE_IF_ERROR(it.SetText(prmName));
353 iBufFlatType = ESqlParamNamesBuf;
354 SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
359 Collects the column values in a flat buffer and returns a reference to the buffer.
361 @leave KErrNoMemory, an out of memory condition has occurred.
363 @return A const reference to a flat buffer containing the column values.
365 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object
367 const RSqlBufFlat& CSqlSrvStatement::ColumnValuesL()
369 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
371 iBufFlatType = static_cast <TSqlBufFlatType> (-1);
372 iBufFlat.SetCount(iColumnCount);
379 ++colIdx;//the first SQLITE column index is 0
380 TInt colType = sqlite3_column_type(iStmtHandle, colIdx);
385 TInt64 val = sqlite3_column_int64(iStmtHandle, colIdx);
386 __SQLLEAVE_IF_ERROR(val == TInt64(TInt32(val)) ? it.SetInt(static_cast <TInt> (val)) : it.SetInt64(val));
390 __SQLLEAVE_IF_ERROR(it.SetReal(sqlite3_column_double(iStmtHandle, colIdx)));
394 TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, colIdx) / sizeof(TUint16);
395 //"charLength == 0" - this might be an indication of an "out of memory" problem, if the column text is in UTF8 format.
396 //(sqlite3_column_bytes16() may allocate memory for UTF8->UTF16 conversion)
397 if(charLength == 0 && sqlite3_errcode(sqlite3_db_handle(iStmtHandle)) == SQLITE_NOMEM)
399 __SQLLEAVE(KErrNoMemory);
401 if(charLength >= KSqlMaxDesLen)
403 it.SetAsNotPresent(ESqlText, charLength);
406 {//sqlite3_column_bytes16() already allocated the needed memory if a UTF8->UTF16 conversion
407 //had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
408 const TUint16* text = reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, colIdx));
409 __ASSERT_DEBUG(text != NULL, __SQLPANIC(ESqlPanicInternalError));
410 __SQLLEAVE_IF_ERROR(it.SetText(TPtrC16(text, charLength)));
416 TInt byteLength = sqlite3_column_bytes(iStmtHandle, colIdx);
417 if(byteLength >= KSqlMaxDesLen)
419 it.SetAsNotPresent(ESqlBinary, byteLength);
423 __SQLLEAVE_IF_ERROR(it.SetBinary(TPtrC8(reinterpret_cast <const TUint8*> (sqlite3_column_blob(iStmtHandle, colIdx)), byteLength)));
431 __ASSERT_DEBUG(EFalse, __SQLPANIC(ESqlPanicInternalError));
433 }//end of switch(...)
434 }//end of - while(it.Next())
435 iBufFlatType = ESqlColumnValuesBuf;
436 SQLPROFILER_REPORT_ALLOC(iBufFlat.MaxSize());
441 This method sets aColumnSource parameter to point to the column data.
443 @param aColumnIndex Column Index, zero based.
444 @param aColumnSource Output parameter. It is set to point to the column data.
446 @return KErrNone, the operation completed successfully;
447 KErrArgument, the refered by aColumnIndex index column is not a binary or text column.
449 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
451 TInt CSqlSrvStatement::ColumnSource(TInt aColumnIndex, TPtrC8& aColumnSource) const
453 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
454 TInt colType = sqlite3_column_type(iStmtHandle, aColumnIndex);
455 if(colType == SQLITE_TEXT)
456 {//Since the first called function after the Next() operation is always CSqlSrvStatement::ColumnValuesL(), then
457 //sqlite3_column_bytes16() (called from ColumnValuesL()) already allocated the needed memory if a UTF8->UTF16
458 //conversion had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
459 const void* text = sqlite3_column_text16(iStmtHandle, aColumnIndex);
460 __ASSERT_DEBUG(text != NULL, __SQLPANIC2(ESqlPanicInternalError));
461 TInt length = sqlite3_column_bytes16(iStmtHandle, aColumnIndex);
462 aColumnSource.Set(reinterpret_cast <const TUint8*> (text), length);
464 else if(colType == SQLITE_BLOB)
466 const void* data = sqlite3_column_blob(iStmtHandle, aColumnIndex);
467 TInt length = sqlite3_column_bytes(iStmtHandle, aColumnIndex);
468 aColumnSource.Set(reinterpret_cast <const TUint8*> (data), length);
478 Retrieves from the SQLITE library columns and parameters count.
480 @panic SqlDb 4 In _DEBUG mode. aDbHandle is NULL.
482 void CSqlSrvStatement::DoCommonConstructL()
484 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
485 iColumnCount = sqlite3_column_count(iStmtHandle);
486 iParamCount = sqlite3_bind_parameter_count(iStmtHandle);
487 __SQLLEAVE_IF_ERROR(iBufFlat.SetCount(Max(iColumnCount, iParamCount)));
491 Destroys the parameter buffer array (used for text or binary parameters).
492 Before the array destruction, each array member is notified that the statement is about to be finalized.
494 void CSqlSrvStatement::DestroyParamBufArray()
496 TInt idx = iParamBufArray.Count();
499 if(iParamBufArray[idx])
501 iParamBufArray[idx]->NotifyStatementFinalized();
504 iParamBufArray.Close();
508 Binds a streamed text or binary parameter value.
510 @param aParamIndex The text/binary parameter index
512 @leave KErrNoMemory, an out of memory condition has occurred;
513 KSqlErrStmtExpired, statement handle has expired.
514 Note that the function may also leave with some other database specific
515 errors categorised as ESqlDbError.
517 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
518 @panic SqlDb 4 In _DEBUG mode. No parameter buffer has been created yet for this parameter.
519 @panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
521 void CSqlSrvStatement::BindParamBufL(TInt aParamIndex)
523 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
524 __ASSERT_DEBUG(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), __SQLPANIC(ESqlPanicBadArgument));
525 __ASSERT_DEBUG(aParamIndex < iParamBufArray.Count(), __SQLPANIC(ESqlPanicBadArgument));
526 __ASSERT_DEBUG(iParamBufArray[aParamIndex] != NULL, __SQLPANIC(ESqlPanicBadArgument));
527 (void)sqlite3SymbianLastOsError();//clear last OS error
528 //Bind the parameter value.
529 //SQLITE_STATIC is used as an argument, because the text/blob data will be kept and can be used by the next bind call
530 HSqlSrvStmtParamBuf& paramBuf = *iParamBufArray[aParamIndex];
531 const TPtrC8 paramData(paramBuf.Data());
532 SQLPROFILER_REPORT_ALLOC(paramData.Length());
534 ++aParamIndex;//SQLite uses positive parameter indexes, the SQL server - parameter indexes begin from 0
535 switch(paramBuf.DataType())
537 case HSqlSrvStmtParamBuf::EText16:
538 //sqlite3_bind_text16() expects 4-th argument to be the bytes count, not the characters count.
539 err = sqlite3_bind_text16(iStmtHandle, aParamIndex, paramData.Ptr(), paramData.Length(), SQLITE_STATIC);
541 case HSqlSrvStmtParamBuf::EBinary:
543 err = sqlite3_bind_blob(iStmtHandle, aParamIndex, paramData.Ptr(), paramData.Length(), SQLITE_STATIC);
546 err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
547 __SQLLEAVE_IF_ERROR(err);
551 @return Represents the content of the column identified by aColIdx as integer value.
552 If the current column type does not refer to an integer, then
553 the function will do a data conversion as described in the table which can be found
557 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
558 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
560 TInt CSqlSrvStatement::ColumnInt(TInt aColIdx) const
562 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
563 __ASSERT_DEBUG((TUint)aColIdx < iColumnCount, __SQLPANIC(ESqlPanicBadArgument));
564 TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
570 TInt err = Math::Round(roundVal, sqlite3_column_double(iStmtHandle, aColIdx), 0);
575 TRealX val(roundVal);
576 return static_cast <TInt> (val);
582 default: //int, int64
584 TInt64 val = sqlite3_column_int64(iStmtHandle, aColIdx);
585 return val == (TInt)val ? (TInt)val : (val < KMinTInt ? KMinTInt : KMaxTInt);
591 @return Represents the content of the column identified by aColIdx as 64-bit integer value.
592 If the current column type does not refer to a 64-bit integer, then
593 the function will do a data conversion as described in the table which can be found
597 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
598 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
600 TInt64 CSqlSrvStatement::ColumnInt64(TInt aColIdx) const
602 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
603 __ASSERT_DEBUG((TUint)aColIdx < iColumnCount, __SQLPANIC(ESqlPanicBadArgument));
604 TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
610 TInt err = Math::Round(roundVal, sqlite3_column_double(iStmtHandle, aColIdx), 0);
615 TRealX val(roundVal);
616 return static_cast <TInt64> (val);
622 default: //int, int64
623 return sqlite3_column_int64(iStmtHandle, aColIdx);
628 @return Represents the content of the column identified by aColIdx as real value.
629 If the current column type does not refer to a real, then
630 the function will do a data conversion as described in the table which can be found
634 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
635 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
637 TReal CSqlSrvStatement::ColumnReal(TInt aColIdx) const
639 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
640 __ASSERT_DEBUG((TUint)aColIdx < iColumnCount, __SQLPANIC(ESqlPanicBadArgument));
641 TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
646 TRealX val(sqlite3_column_int64(iStmtHandle, aColIdx));
647 return static_cast <TReal> (val);
654 return sqlite3_column_double(iStmtHandle, aColIdx);
659 Represents the content of the column identified by aColIdx as text (16 bit) descriptor.
660 If the current column type does not refer to a text block of data, then
661 the function will do a data conversion as described in the table which can be found
666 @leave KErrNoMemory, an out of memory condition has occurred.
668 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
669 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
671 TPtrC CSqlSrvStatement::ColumnTextL(TInt aColIdx) const
673 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
674 __ASSERT_DEBUG((TUint)aColIdx < iColumnCount, __SQLPANIC(ESqlPanicBadArgument));
676 TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
677 if(colType == SQLITE_TEXT)
679 TInt charLength = (TUint)sqlite3_column_bytes16(iStmtHandle, aColIdx) / sizeof(TUint16);
680 //"charLength == 0" - this might be an indication of an "out of memory" problem, if the column text is in UTF8 format.
681 //(sqlite3_column_bytes16() may allocate memory for UTF8->UTF16 conversion)
682 if(charLength == 0 && sqlite3_errcode(sqlite3_db_handle(iStmtHandle)) == SQLITE_NOMEM)
684 __SQLLEAVE(KErrNoMemory);
686 //sqlite3_column_bytes16() already allocated the needed memory if a UTF8->UTF16 conversion
687 //had to be performed. The sqlite3_column_text16() on the next line is guaranteed to succeed.
688 const TUint16* text = reinterpret_cast <const TUint16*> (sqlite3_column_text16(iStmtHandle, aColIdx));
689 __ASSERT_DEBUG(text != NULL, __SQLPANIC(ESqlPanicInternalError));
690 res.Set(text, charLength);
696 Represents the content of the column identified by aColIdx as binary (8 bit) descriptor.
697 If the current column type does not refer to a binary block of data, then
698 the function will do a data conversion as described in the table which can be found
703 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
704 @panic SqlDb 4 In _DEBUG mode. Invalid aColIdx value.
706 TPtrC8 CSqlSrvStatement::ColumnBinary(TInt aColIdx) const
708 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
709 __ASSERT_DEBUG((TUint)aColIdx < iColumnCount, __SQLPANIC(ESqlPanicBadArgument));
711 TInt colType = sqlite3_column_type(iStmtHandle, aColIdx);
712 if(colType == SQLITE_BLOB)
714 TInt byteLength = sqlite3_column_bytes(iStmtHandle, aColIdx);
715 res.Set(reinterpret_cast <const TUint8*> (sqlite3_column_blob(iStmtHandle, aColIdx)), byteLength);
721 Retrieves the declared column types using the SQLITE library storing in a
722 flat buffer and returns a reference to the buffer.
724 @return A const reference to a flat buffer containing the declared column type names.
726 @leave KErrNoMemory, an out of memory condition has occurred;
728 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
730 const RSqlBufFlat& CSqlSrvStatement::GetDeclColumnTypesL()
732 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
733 iBufFlatType = static_cast <TSqlBufFlatType> (-1);
734 __SQLLEAVE_IF_ERROR(iBufFlat.SetCount(iColumnCount));
740 ++colIdx;//the first SQLITE column index is 0
741 const TUint16* declTypeTxt = reinterpret_cast <const TUint16*> (sqlite3_column_decltype16(iStmtHandle, colIdx));
742 TPtrC ptr(KNullDesC);
745 ptr.Set(declTypeTxt, User::StringLength(declTypeTxt));
749 //If sqlite3_column_decltype16() returns NULL but sqlite3_column_decltype() doesn't, then it is an "out of memory" condition
750 if(sqlite3_column_decltype(iStmtHandle, colIdx))
752 __SQLLEAVE(KErrNoMemory);
755 __SQLLEAVE_IF_ERROR(it.SetText(ptr));
757 iBufFlatType = ESqlDeclColumnTypesBuf;
763 Creates a new HSqlSrvStmtParamBuf object for the parameter with index "aParamIndex" or
764 reuses the existing one.
766 @param aParamIndex Parameter index, zero based.
767 @param aDataType Parameter value type - binary, text8 or text16.
768 @param aIsStreamBuf True if the param data will be retrieved from an IPC stream
770 @return A pointer to the created HSqlSrvStmtParamBuf instance.
772 @leave KErrNoMemory, an out of memory condition has occurred;
774 HSqlSrvStmtParamBuf* CSqlSrvStatement::GetParamBufL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType,
775 HSqlSrvStmtParamBuf::TBufType aBufType)
777 __ASSERT_DEBUG(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), __SQLPANIC(ESqlPanicBadArgument));
778 ExtendParamBufArrayL(aParamIndex);
779 HSqlSrvStmtParamBuf*& paramBuf = iParamBufArray[aParamIndex];
781 {//Reset and reuse the existing buffer
782 __ASSERT_DEBUG(paramBuf->ParamIndex() == aParamIndex, __SQLPANIC(ESqlPanicInternalError));
783 paramBuf->Reset(aDataType, aBufType);
787 paramBuf = HSqlSrvStmtParamBuf::NewL(*this, aParamIndex, aDataType, aBufType);
793 This function will extend the iParamBufArray array (filling the new array items with NULL), if it is needed -
794 to ensure that there is enough place in the buffer for the parameter identified by aParamIndex.
796 @param aParamIndex The parameter index
798 @leave KErrNoMemory, an out of memory condition has occurred;
800 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
801 @panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
803 void CSqlSrvStatement::ExtendParamBufArrayL(TInt aParamIndex)
805 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
806 __ASSERT_DEBUG(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), __SQLPANIC(ESqlPanicBadArgument));
807 TInt ext = aParamIndex - iParamBufArray.Count() + 1;
810 __SQLLEAVE_IF_ERROR(iParamBufArray.Append(NULL));
815 This function will create a copy of the aParamValue and store it in the iParamBufArray array for later use.
816 The reason: once bound, the parameter value can be used multiple times by the SQLite if it is not set explicitly again.
818 @param aParamIndex The parameter index
819 @param aDataType Parameter value type - binary, text8 or text16.
820 @param aParamValue The parameter value
822 @return 8-bit descriptor to the stored parameter value
824 @leave KErrNoMemory, an out of memory condition has occurred;
826 @panic SqlDb 2 In _DEBUG mode. Invalid (not created) CSqlSrvStatement object.
827 @panic SqlDb 4 In _DEBUG mode. Parameter index out of bounds.
829 TPtrC8 CSqlSrvStatement::CopyAndStoreParamL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, const TDesC8& aParamValue)
831 __ASSERT_DEBUG(iStmtHandle != NULL, __SQLPANIC(ESqlPanicInvalidObj));
832 __ASSERT_DEBUG(aParamIndex >= 0 && aParamIndex < sqlite3_bind_parameter_count(iStmtHandle), __SQLPANIC(ESqlPanicBadArgument));
833 HSqlSrvStmtParamBuf* paramBuf = GetParamBufL(aParamIndex, aDataType, HSqlSrvStmtParamBuf::EBufSimpleBind);
834 return paramBuf->SetDataL(aParamValue);