commands/sql/sqlsrv.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     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 	}