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