|
1 // sqlsrv.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #include "sqlsrv.h" |
|
13 |
|
14 #include "sqlcmd_open.h" |
|
15 |
|
16 _LIT(KNewLine, "\r\n"); |
|
17 _LIT(KPrompt, "ok\r\n"); |
|
18 |
|
19 _LIT(KHistoryFile, "c:\\system\\console\\fshell_sqlsrv\\history"); |
|
20 |
|
21 const TInt KFileBufferSize = 32768; |
|
22 |
|
23 CCmdSqlSrv* CCmdSqlSrv::iOnlyInstance = NULL; |
|
24 |
|
25 CCommandBase* CCmdSqlSrv::NewLC() |
|
26 { |
|
27 if (CCmdSqlSrv::iOnlyInstance) |
|
28 { |
|
29 User::LeaveIfError(KErrAlreadyExists); |
|
30 } |
|
31 |
|
32 CCmdSqlSrv* self = new (ELeave)CCmdSqlSrv(); |
|
33 CCmdSqlSrv::iOnlyInstance = self; |
|
34 CleanupStack::PushL(self); |
|
35 self->BaseConstructL(); |
|
36 return self; |
|
37 } |
|
38 |
|
39 //static: |
|
40 //Check if a string is wrapped by double quote, and removed them |
|
41 // |
|
42 void CCmdSqlSrv::StripWrapDoubleQuote(HBufC& aText) |
|
43 { |
|
44 RBuf text; |
|
45 text.Create(aText); |
|
46 text.Trim(); |
|
47 if (text.Left(1)==_L("\"") && text.Right(1)== _L("\"")) |
|
48 { |
|
49 //delete right side quote |
|
50 text.Delete(text.Length()-1, 1); |
|
51 //delete left side quote |
|
52 text.Delete(0,1); |
|
53 aText = text; |
|
54 } |
|
55 text.Close(); |
|
56 } |
|
57 |
|
58 |
|
59 |
|
60 //static |
|
61 CCmdSqlSrv* CCmdSqlSrv::GetServer() |
|
62 { |
|
63 return CCmdSqlSrv::iOnlyInstance; |
|
64 } |
|
65 |
|
66 CCmdSqlSrv::CCmdSqlSrv() |
|
67 : CServerBase(0, KPrompt, KHistoryFile), iNextCommandId(1) |
|
68 { |
|
69 iTmpFileNo = 1; |
|
70 iDatabaseOpened = EFalse; |
|
71 } |
|
72 |
|
73 void CCmdSqlSrv::ConstructL() |
|
74 { |
|
75 BaseConstructL(); |
|
76 } |
|
77 |
|
78 CCmdSqlSrv::~CCmdSqlSrv() |
|
79 { |
|
80 iSqlDb.Close(); |
|
81 CCmdSqlSrv::iOnlyInstance = NULL; |
|
82 } |
|
83 |
|
84 ////////////////////////////////////////////////////// |
|
85 |
|
86 |
|
87 ////////////////////////////////////////////////////// |
|
88 |
|
89 const TDesC& CCmdSqlSrv::Name() const |
|
90 { |
|
91 _LIT(KName, "sqlsrv"); |
|
92 return KName; |
|
93 } |
|
94 |
|
95 const TDesC& CCmdSqlSrv::Description() const |
|
96 { |
|
97 _LIT(KDescription, "a command to interact with Symbian SQLite server"); |
|
98 return KDescription; |
|
99 } |
|
100 |
|
101 void CCmdSqlSrv::ArgumentsL(RCommandArgumentList& /*aArguments*/) |
|
102 { |
|
103 } |
|
104 |
|
105 void CCmdSqlSrv::OptionsL(RCommandOptionList& /*aOptions*/) |
|
106 { |
|
107 } |
|
108 |
|
109 TInt CCmdSqlSrv::NextCommandId() |
|
110 { |
|
111 return iNextCommandId++; |
|
112 } |
|
113 |
|
114 //when retrieving SQL records, if there is any binary columns and user has specified |
|
115 //a Temp file template, then we will generate a temp file and dump the binary into such file. |
|
116 void CCmdSqlSrv::MakeTempFilename(TDes& aTmpFile, TDesC& aTemplate) |
|
117 { |
|
118 TFileName2 tmpTemplate(aTemplate); |
|
119 TPtrC drvPath = tmpTemplate.DriveAndPath(); |
|
120 TPtrC name = tmpTemplate.Name(); |
|
121 TPtrC ext = tmpTemplate.Ext(); |
|
122 |
|
123 aTmpFile.Format(_L("%S%S.%02d%S"), &drvPath, &name, iTmpFileNo, &ext); |
|
124 iTmpFileNo++; |
|
125 } |
|
126 |
|
127 |
|
128 void CCmdSqlSrv::ReportResult(const TServerCommandId& aId, const TDesC& aName, TRefByValue<const TDesC> aFmt, ...) |
|
129 { |
|
130 CheckNewConsoleLine(); |
|
131 DoPrintf(_L("result:%u:%S:"), aId.Value(), &aName); |
|
132 VA_LIST list; |
|
133 VA_START(list, aFmt); |
|
134 DoPrintList(aFmt, list, ENewLine); |
|
135 VA_END(list); |
|
136 } |
|
137 |
|
138 |
|
139 void CCmdSqlSrv::InitializeL() |
|
140 { |
|
141 CServerCommandFactory& factory = Factory(); |
|
142 |
|
143 factory.AddLeafCommandL<CSqlCmdExit>(); |
|
144 factory.AddLeafCommandL<CSqlCmdOpen>(); |
|
145 factory.AddLeafCommandL<CSqlCmdCreate>(); |
|
146 factory.AddLeafCommandL<CSqlCmdExec>(); |
|
147 factory.AddLeafCommandL<CSqlCmdClose>(); |
|
148 factory.AddLeafCommandL<CSqlCmdState>(); |
|
149 factory.AddLeafCommandL<CSqlCmdAttach>(); |
|
150 factory.AddLeafCommandL<CSqlCmdDetach>(); |
|
151 |
|
152 #ifdef SQL_COMPACT |
|
153 factory.AddLeafCommandL<CSqlCmdCompact>(); |
|
154 #endif |
|
155 |
|
156 } |
|
157 |
|
158 void CCmdSqlSrv::DoPrintf(TRefByValue<const TDesC> aFmt, ...) |
|
159 { |
|
160 VA_LIST list; |
|
161 VA_START(list, aFmt); |
|
162 DoPrintList(aFmt, list); |
|
163 VA_END(list); |
|
164 } |
|
165 |
|
166 void CCmdSqlSrv::DoPrintf(TRefByValue<const TDesC8> aFmt, ...) |
|
167 { |
|
168 VA_LIST list; |
|
169 VA_START(list, aFmt); |
|
170 DoPrintList(aFmt, list); |
|
171 VA_END(list); |
|
172 } |
|
173 |
|
174 void CCmdSqlSrv::DoPrintList(TRefByValue<const TDesC> aFmt, VA_LIST& aList, TPrintPostfix aPostfix) |
|
175 { |
|
176 TOverflowTruncate overflow; |
|
177 TBuf<0x100> buf; |
|
178 buf.AppendFormatList(aFmt, aList, &overflow); |
|
179 DoPrint(buf, aPostfix); |
|
180 } |
|
181 |
|
182 void CCmdSqlSrv::DoPrintList(TRefByValue<const TDesC8> aFmt, VA_LIST& aList, TPrintPostfix aPostfix) |
|
183 { |
|
184 TOverflowTruncate8 overflow; |
|
185 TBuf8<0x200> buf; |
|
186 buf.AppendFormatList(aFmt, aList, &overflow); |
|
187 if (buf.Length() > 0x100) buf.SetLength(0x100); // Truncate to half the buffer size so that the call to Expand doesn't panic |
|
188 TPtrC wideBuf = buf.Expand(); |
|
189 DoPrint(wideBuf, aPostfix); |
|
190 } |
|
191 |
|
192 void CCmdSqlSrv::DoPrint(const TDesC& aDes, TPrintPostfix aPostfix) |
|
193 { |
|
194 Stdout().Write(aDes); |
|
195 if ((aPostfix == ENewLine) && ((aDes.Length() < KNewLine().Length()) || (aDes.Right(KNewLine().Length()) != KNewLine))) |
|
196 { |
|
197 Stdout().Write(KNewLine); |
|
198 } |
|
199 } |
|
200 |
|
201 |
|
202 void CCmdSqlSrv::Report(const TServerCommandId& /*aId*/, const TDesC& /*aDes*/) |
|
203 { |
|
204 //TODO? |
|
205 // Log(aId, aDes); |
|
206 } |
|
207 |
|
208 void CCmdSqlSrv::Report(const TServerCommandId& /*aId*/, const TDesC8& /*aDes*/) |
|
209 { |
|
210 //TODO? |
|
211 // Log(aId, aDes); |
|
212 } |
|
213 |
|
214 void CCmdSqlSrv::ReportWarning(const TServerCommandId& aId, const TDesC& aDes) |
|
215 { |
|
216 CheckNewConsoleLine(); |
|
217 DoPrintf(_L("warning:%u:%S\r\n"), aId.Value(), &aDes); |
|
218 } |
|
219 |
|
220 void CCmdSqlSrv::ReportError(const TServerCommandId& aId, TInt aError, const TDesC& aDes) |
|
221 { |
|
222 CheckNewConsoleLine(); |
|
223 DoPrintf(_L("error:%d:%u:%S\r\n"), aError, aId.Value(), &aDes); |
|
224 } |
|
225 |
|
226 //////////////////////////////////////////////////////////////////////////// |
|
227 //////////////////////////////////////////////////////////////////////////// |
|
228 |
|
229 //aCommand: the command which is invoking this function, SHOULD NOT BE NULL |
|
230 // |
|
231 void CCmdSqlSrv::SqlCreateL(TDesC& aFilename, CServerCommandBase* aCommand) |
|
232 { |
|
233 if (iDatabaseOpened) |
|
234 LeaveIfErr(KErrGeneral, _L("A database is already opened")); |
|
235 |
|
236 iSqlDb.CreateL(aFilename); |
|
237 |
|
238 //Print size information if no error occurrs |
|
239 TInt size = iSqlDb.Size(); |
|
240 ReportResult(aCommand->Id(), aCommand->Name(), _L("Database created, size: %d bytes.\r\n"), size); |
|
241 iDatabaseOpened = ETrue; |
|
242 } |
|
243 |
|
244 void CCmdSqlSrv::SqlOpenL(TDesC& aFilename, CServerCommandBase* aCommand) |
|
245 { |
|
246 if (iDatabaseOpened) |
|
247 LeaveIfErr(KErrGeneral, _L("A database is already opened")); |
|
248 |
|
249 iSqlDb.OpenL(aFilename); |
|
250 |
|
251 //Print size information if no error occurrs |
|
252 TInt size = iSqlDb.Size(); |
|
253 ReportResult(aCommand->Id(), aCommand->Name(), _L("Database opened, size: %d bytes.\r\n"), size); |
|
254 iDatabaseOpened = ETrue; |
|
255 |
|
256 //more detailed size information seems only available from Symbian OS 9.5 or later. |
|
257 /* |
|
258 RSqlDatabase::TSize size; |
|
259 iSqlDb.Size(size); |
|
260 ReportResult(aCommand->Id(), aCommand->Name(), _L("Database opened, size: %Ld bytes. free:%Ld bytes\r\n"), |
|
261 size.iSize, size.iFree); |
|
262 */ |
|
263 } |
|
264 |
|
265 //execute a SQL statement without parameter/response |
|
266 void CCmdSqlSrv::SqlExecL(TDesC& aStatement, CServerCommandBase* aCommand) |
|
267 { |
|
268 TInt err; |
|
269 if (!iDatabaseOpened) |
|
270 LeaveIfErr(KErrGeneral, _L("No database opened")); |
|
271 |
|
272 err = iSqlDb.Exec(aStatement); |
|
273 |
|
274 if (err < 0) |
|
275 { |
|
276 TPtrC errMsg = iSqlDb.LastErrorMessage(); |
|
277 ReportResult(aCommand->Id(), aCommand->Name(), _L("Exec return code:%d message:%S\r\n"), |
|
278 err, &errMsg); |
|
279 } |
|
280 |
|
281 User::LeaveIfError(err); |
|
282 |
|
283 //print the return code if it's not error |
|
284 ReportResult(aCommand->Id(), aCommand->Name(), _L("Exec return code:%d\r\n"),err); |
|
285 } |
|
286 |
|
287 //execute a SQL statement with parameter/response |
|
288 //aStatement: SQL statement |
|
289 //aOptParamFile: contains multiple string (HBufC*):should be parameters for that statement |
|
290 //aTempFileTemplate: template to generate temp file, used to dump binary contents |
|
291 void CCmdSqlSrv::SqlStateL(TDesC& aStatement, RPointerArray<HBufC> &aOptParamFile, CServerCommandBase* aCommand, TDesC* aTempFileTemplate) |
|
292 { |
|
293 TInt err; |
|
294 if (!iDatabaseOpened) |
|
295 LeaveIfErr(KErrGeneral, _L("No database opened")); |
|
296 |
|
297 RSqlStatement sqlState; |
|
298 CleanupClosePushL(sqlState); |
|
299 |
|
300 err = sqlState.Prepare(iSqlDb, aStatement); |
|
301 if (err < 0) |
|
302 { |
|
303 TPtrC errMsg = iSqlDb.LastErrorMessage(); |
|
304 ReportResult(aCommand->Id(), aCommand->Name(), _L("RSqlStatement::Prepare() return code:%d message:%S\r\n"), |
|
305 err, &errMsg); |
|
306 } |
|
307 User::LeaveIfError(err); |
|
308 |
|
309 //depend on the statement type, for something like SELECT, which is expected to have returned results, |
|
310 //we should call Next(), |
|
311 //otherwise we should call Exec(); |
|
312 //Panic will occur if calling wrong function |
|
313 //so check if this statement is SELECT |
|
314 TBool bIsSelect; |
|
315 TBuf<64> strBegin; |
|
316 strBegin.Copy(aStatement.Left(64)); |
|
317 strBegin.TrimLeft(); |
|
318 strBegin.UpperCase(); |
|
319 |
|
320 if (strBegin.Left(6)==_L("SELECT")) |
|
321 bIsSelect = ETrue; |
|
322 else |
|
323 bIsSelect = EFalse; |
|
324 |
|
325 if (bIsSelect) |
|
326 { |
|
327 //once successfully execute the statement, check if there is any response. |
|
328 //only quit the loop when there is no more results found |
|
329 TInt totalRecordsReturned = 0; |
|
330 while(ETrue) |
|
331 { |
|
332 err = sqlState.Next(); |
|
333 if (err==KSqlAtRow) //ready to retrieve a result (usual response for SELECT command) |
|
334 { |
|
335 totalRecordsReturned++; |
|
336 ReportResult(aCommand->Id(), aCommand->Name(), _L("Record #%d =========================\r\n"), totalRecordsReturned); |
|
337 |
|
338 ParseResultL(sqlState, aCommand, aTempFileTemplate); |
|
339 |
|
340 } |
|
341 else if (err==KSqlAtEnd) //no records found |
|
342 { |
|
343 ReportResult(aCommand->Id(), aCommand->Name(), _L("===================================\r\n")); |
|
344 ReportResult(aCommand->Id(), aCommand->Name(), _L("%d record(s) returned\r\n"), totalRecordsReturned); |
|
345 break; |
|
346 } |
|
347 else |
|
348 { |
|
349 User::LeaveIfError(err); |
|
350 } |
|
351 } |
|
352 } |
|
353 else |
|
354 { |
|
355 RSqlParamWriteStream strm; //only will have effect when parameters are used |
|
356 CleanupClosePushL(strm); |
|
357 //check if there is any parameters that need to be bound with the statement |
|
358 TInt paramCnt = aOptParamFile.Count(); |
|
359 if (paramCnt) |
|
360 { |
|
361 for (TInt paramId = 0; paramId<paramCnt; paramId++) |
|
362 { |
|
363 HBufC* paramFile = aOptParamFile[paramId]; |
|
364 RFile file; |
|
365 CleanupClosePushL(file); |
|
366 err = file.Open(FsL(), *paramFile, EFileRead); |
|
367 LeaveIfErr(err, _L("Error openning file %S"), paramFile); |
|
368 |
|
369 err = strm.BindBinary(sqlState, paramId); |
|
370 User::LeaveIfError(err); |
|
371 |
|
372 //dump the file content the the parameter |
|
373 //file could be very large, so it is wise to separate it into several times. each time 32K or so. |
|
374 { |
|
375 TInt fileSize; |
|
376 file.Size(fileSize); |
|
377 RBuf8 buf; |
|
378 buf.CreateL(KFileBufferSize); //each time 32KB |
|
379 |
|
380 for (TInt curPos = 0; curPos<fileSize ;) |
|
381 { |
|
382 TInt remaingBytes = (fileSize-curPos); |
|
383 TInt bytesToProc = (remaingBytes>KFileBufferSize)? KFileBufferSize : remaingBytes; |
|
384 err = file.Read(curPos, buf, bytesToProc); |
|
385 User::LeaveIfError(err); |
|
386 |
|
387 strm.WriteL(buf); |
|
388 curPos += bytesToProc; |
|
389 } |
|
390 |
|
391 buf.Close(); |
|
392 strm.CommitL(); |
|
393 strm.Close(); |
|
394 } |
|
395 |
|
396 CleanupStack::PopAndDestroy(); //file |
|
397 } |
|
398 |
|
399 } |
|
400 err = sqlState.Exec(); |
|
401 ReportResult(aCommand->Id(), aCommand->Name(), _L("Exec return code:%d\r\n"),err); |
|
402 |
|
403 CleanupStack::PopAndDestroy(); //strm |
|
404 } |
|
405 |
|
406 CleanupStack::PopAndDestroy(); |
|
407 } |
|
408 |
|
409 |
|
410 //close SQL database file |
|
411 void CCmdSqlSrv::SqlClose(CServerCommandBase* aCommand) |
|
412 { |
|
413 if (!iDatabaseOpened) |
|
414 LeaveIfErr(KErrGeneral, _L("No database opened")); |
|
415 |
|
416 iSqlDb.Close(); |
|
417 //print the return code if it's not error |
|
418 ReportResult(aCommand->Id(), aCommand->Name(), _L("SQL database file closed\r\n")); |
|
419 iDatabaseOpened = EFalse; |
|
420 } |
|
421 |
|
422 //attach additional database onto main database |
|
423 void CCmdSqlSrv::SqlAttachL(TDesC& aFilename, TDesC& aDateBaseName, CServerCommandBase* aCommand) |
|
424 { |
|
425 TInt err; |
|
426 if (!iDatabaseOpened) |
|
427 LeaveIfErr(KErrGeneral, _L("No database opened")); |
|
428 |
|
429 err = iSqlDb.Attach(aFilename, aDateBaseName); |
|
430 ReportResult(aCommand->Id(), aCommand->Name(), _L("RSqlDatabase::Attach return code:%d\r\n"), err); |
|
431 User::LeaveIfError(err); |
|
432 } |
|
433 |
|
434 // |
|
435 void CCmdSqlSrv::SqlDetachL(TDesC& aDateBaseName, CServerCommandBase* aCommand) |
|
436 { |
|
437 TInt err; |
|
438 if (!iDatabaseOpened) |
|
439 LeaveIfErr(KErrGeneral, _L("No database opened")); |
|
440 |
|
441 err = iSqlDb.Detach(aDateBaseName); |
|
442 ReportResult(aCommand->Id(), aCommand->Name(), _L("RSqlDatabase::Detach return code:%d\r\n"), err); |
|
443 User::LeaveIfError(err); |
|
444 } |
|
445 |
|
446 #ifdef SQL_COMPACT |
|
447 //RSqlDatabase::Compact() is documented but not implemented, so Do not use for now |
|
448 //aDateBaseName: can be NULL (compacting main database) |
|
449 void CCmdSqlSrv::SqlCompactL(TDesC* aDateBaseName, CServerCommandBase* aCommand) |
|
450 { |
|
451 TInt err; |
|
452 err = iSqlDb.Compact(0, aDateBaseName); |
|
453 ReportResult(aCommand->Id(), aCommand->Name(), _L("RSqlDatabase::Compact return code:%d\r\n"), err); |
|
454 User::LeaveIfError(err); |
|
455 } |
|
456 #endif |
|
457 |
|
458 //////////////////////////////////////////////////////////////////////////////////////////// |
|
459 |
|
460 |
|
461 //once we got a result from a SELECT command, then we go through the returned result |
|
462 //only call this function after calling Next(). |
|
463 //we only analyse ONE returned record in this function |
|
464 void CCmdSqlSrv::ParseResultL(RSqlStatement& aState, CServerCommandBase* aCommand, TDesC* aTempFileTemplate) |
|
465 { |
|
466 TInt err; |
|
467 TInt colCnt = aState.ColumnCount(); |
|
468 TBuf<64> colHdr; //column information fixed header |
|
469 |
|
470 for (TInt i=0; i<colCnt; i++) |
|
471 { |
|
472 TPtrC columnName; |
|
473 err = aState.ColumnName(i, columnName); |
|
474 if (err != KErrNone) |
|
475 { |
|
476 _LIT(KNotAvailable, "N/A"); |
|
477 columnName.Set(KNotAvailable); |
|
478 } |
|
479 |
|
480 TSqlColumnType colType = aState.ColumnType(i); |
|
481 const TDesC* pTypeStr = ColumnTypeToString(colType); |
|
482 TInt colSize = aState.ColumnSize(i); |
|
483 |
|
484 colHdr.Format(_L("Column %d \"%S\"(%S)"), i, &columnName, pTypeStr); |
|
485 |
|
486 switch(colType) |
|
487 { |
|
488 case ESqlNull: |
|
489 { |
|
490 ReportResult(aCommand->Id(), aCommand->Name(), _L("%S \r\n"), &colHdr); |
|
491 break; |
|
492 } |
|
493 case ESqlInt: |
|
494 { |
|
495 TInt colValue = aState.ColumnInt(i); |
|
496 ReportResult(aCommand->Id(), aCommand->Name(), _L("%S %d\r\n"), &colHdr, colValue); |
|
497 break; |
|
498 } |
|
499 case ESqlInt64: |
|
500 { |
|
501 TInt64 colValue = aState.ColumnInt64(i); |
|
502 ReportResult(aCommand->Id(), aCommand->Name(),_L("%S %Ld\r\n"), &colHdr , colValue); |
|
503 break; |
|
504 } |
|
505 case ESqlReal: |
|
506 { |
|
507 TInt64 colValue = aState.ColumnReal(i); |
|
508 ReportResult(aCommand->Id(), aCommand->Name(),_L("%S %f\r\n"), &colHdr, colValue); |
|
509 break; |
|
510 } |
|
511 case ESqlText: |
|
512 { |
|
513 TPtrC colValue = aState.ColumnTextL(i); |
|
514 ReportResult(aCommand->Id(), aCommand->Name(),_L("%S %S\r\n"), &colHdr, &colValue); |
|
515 break; |
|
516 } |
|
517 case ESqlBinary: |
|
518 { |
|
519 TBool dumpToFile = EFalse; |
|
520 TBuf<128> printableHex; |
|
521 TFileName tmpFileName; |
|
522 |
|
523 RSqlColumnReadStream strm; |
|
524 CleanupClosePushL(strm); |
|
525 err = strm.ColumnBinary(aState, i); |
|
526 |
|
527 //generate a temp file name for dumping binary content |
|
528 RFile tmpFile; |
|
529 CleanupClosePushL(tmpFile); |
|
530 if (aTempFileTemplate && aTempFileTemplate->Length()>0 ) |
|
531 { |
|
532 MakeTempFilename(tmpFileName, *aTempFileTemplate); |
|
533 //open the file |
|
534 err = tmpFile.Replace(FsL(), tmpFileName, EFileWrite); |
|
535 if (err==KErrNone) |
|
536 dumpToFile = ETrue; |
|
537 } |
|
538 |
|
539 //go through the binary content, and dump it if tmp file is available |
|
540 RBuf8 readBuf; |
|
541 CleanupClosePushL(readBuf); |
|
542 readBuf.CreateL(KFileBufferSize); |
|
543 for(TInt cursor=0; cursor < colSize; ) |
|
544 { |
|
545 TInt bytesRemain = (colSize-cursor); |
|
546 TInt bytesToProc = (bytesRemain>KFileBufferSize) ? KFileBufferSize : bytesRemain; |
|
547 strm.ReadL(readBuf, bytesToProc); |
|
548 |
|
549 if (cursor==0) //it is beginning the binary data, always print first few bytes on screen |
|
550 { |
|
551 TInt byteCnt = bytesToProc; |
|
552 TInt byteToPrint = (byteCnt > 32)? 32 : byteCnt; |
|
553 printableHex.AppendFormat(_L("DataLength:%d Hex: "), colSize); |
|
554 |
|
555 for (TInt a=0; a<byteToPrint; a++) |
|
556 { |
|
557 TInt byteVal = readBuf[a]; |
|
558 printableHex.AppendFormat(_L("%02x "), byteVal); |
|
559 } |
|
560 if (byteToPrint < byteCnt) |
|
561 printableHex.AppendFormat(_L("...")); |
|
562 } |
|
563 |
|
564 if (dumpToFile) |
|
565 { |
|
566 err = tmpFile.Write(cursor, readBuf, bytesToProc); |
|
567 if (err != KErrNone) |
|
568 { |
|
569 dumpToFile = EFalse; |
|
570 break; |
|
571 } |
|
572 } |
|
573 else |
|
574 break; |
|
575 |
|
576 cursor += bytesToProc; |
|
577 } |
|
578 CleanupStack::PopAndDestroy(); //readBuf |
|
579 CleanupStack::PopAndDestroy(); //tmpFile |
|
580 CleanupStack::PopAndDestroy();//strm; |
|
581 ReportResult(aCommand->Id(), aCommand->Name(),_L("%S %S\r\n"), &colHdr, &printableHex); |
|
582 if (dumpToFile) |
|
583 { |
|
584 ReportResult(aCommand->Id(), aCommand->Name(),_L("Binary content dumped to file %S\r\n"), |
|
585 &tmpFileName); |
|
586 } |
|
587 } |
|
588 break; |
|
589 } |
|
590 |
|
591 } |
|
592 } |
|
593 |
|
594 |
|
595 |
|
596 EXE_BOILER_PLATE(CCmdSqlSrv) |
|
597 |
|
598 #define CASE_LIT(x) case x: { _LIT(KName, #x); pString = &KName; break; } |
|
599 |
|
600 //static |
|
601 const TDesC* CCmdSqlSrv::ColumnTypeToString(TSqlColumnType aType) |
|
602 { |
|
603 const TDesC* pString = NULL; |
|
604 switch(aType) |
|
605 { |
|
606 CASE_LIT(ESqlNull); |
|
607 CASE_LIT(ESqlInt); |
|
608 CASE_LIT(ESqlInt64); |
|
609 CASE_LIT(ESqlReal); |
|
610 CASE_LIT(ESqlText); |
|
611 CASE_LIT(ESqlBinary); |
|
612 default: |
|
613 _LIT(KUnknowStr, "Unknown"); |
|
614 pString = &KUnknowStr; |
|
615 } |
|
616 return pString; |
|
617 } |
|
618 |
|
619 void CCmdSqlSrv::PrintTime(const TTime& aTime, TBool aNewline) |
|
620 { |
|
621 TTime NullTime = Time::NullTTime(); |
|
622 if (aTime == NullTime) |
|
623 { |
|
624 Printf(_L("(NullTime)")); |
|
625 } |
|
626 else |
|
627 { |
|
628 _LIT8(KDateTimeFormat, "%d-%02d-%02d %02d:%02d:%02d"); |
|
629 TDateTime dt = aTime.DateTime(); |
|
630 Printf(KDateTimeFormat, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second()); |
|
631 } |
|
632 |
|
633 if (aNewline) Printf(_L("\r\n")); |
|
634 } |