persistentstorage/dbms/tdbms/t_dbscript.cpp
changeset 0 08ec8eefde2f
child 55 44f437012c90
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 1998-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 <d32dbms.h>
       
    17 #include <f32file.h>
       
    18 #include <e32test.h>
       
    19 #include <e32math.h>
       
    20 #include <d32dbmsconstants.h>
       
    21 
       
    22 LOCAL_D RTest TheTest(_L("t_dbscript"));
       
    23 LOCAL_D CTrapCleanup* TheTrapCleanup;
       
    24 LOCAL_D RDbNamedDatabase TheDatabase;
       
    25 LOCAL_D RFs TheFs;
       
    26 LOCAL_D RDbView TheView;
       
    27 //
       
    28 const TPtrC KTestDatabase=_L("c:\\dbms-tst\\t_script.db");
       
    29 
       
    30 const TPtrC KRomScriptFile=_L("z:\\test\\t_script.txt");
       
    31 
       
    32 const TPtrC KOutputFile=_L("c:\\dbms-tst\\t_script.log");
       
    33 
       
    34 const TInt KTestCleanupStack=0x20;
       
    35 const TPtrC KDDLKeywords[]={_L("CREATE"),_L("DROP"),_L("ALTER")};
       
    36 const TPtrC KDMLKeywords[]={_L("INSERT"),_L("DELETE"),_L("UPDATE")};
       
    37 const TPtrC KQueryKeywords[]={_L("SELECT")};
       
    38 const TPtrC KScriptKeywords[]={_L("PRINT"),_L("ROWS"),_L("COMPARE"),_L("ERROR"),_L("!"),
       
    39 							   _L("POPULATE"),_L("RESULTS"),_L("BUILD"),_L("QUERY"),
       
    40 							   _L("NORMAL"),_L("FOLDED"),_L("COLLATED"),_L("START"),_L("STOP"),
       
    41 							   _L("LOAD"),_L("ECHO"),_L("WINDOW"),_L("ACCESS")};
       
    42 const TPtrC KRowIdColName=_L("Rw");
       
    43 enum TKeyword {EPrint,ERows,ECompare,EError,EComment,EPopulate,EResults,EBuild,EQuery,ENormal,
       
    44                EFolded,ECollated,EStart,EStop,ELoad,EEcho,EWindow,EAccess,ENumKeywords,EUnknown};
       
    45 //
       
    46 typedef TBuf<256> TScriptLine;
       
    47 typedef TBuf<256> TScriptToken;
       
    48 //
       
    49 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
       
    50 
       
    51 class TScript;
       
    52 class TTimer
       
    53 	{
       
    54 public:
       
    55 	inline TTimer(TScript& aScript);
       
    56 	void Start(const TDesC& aDes);
       
    57 	void Stop(const TDesC& aDes);
       
    58 private:
       
    59 	TUint iTicks;
       
    60 	TScript& iScript;
       
    61 	};
       
    62 
       
    63 class TResults
       
    64 	{
       
    65 public:
       
    66 	inline TResults();
       
    67 public:
       
    68 	RDbView& iView;
       
    69 	TInt iError;
       
    70 	TInt iRows;
       
    71 	TInt iLineNo;
       
    72 	TScriptLine iLine;
       
    73 	};
       
    74 
       
    75 class TSqlStatement
       
    76 	{
       
    77 private:
       
    78 	enum TSqlType {EDML,EDDL,EQuery,EUnknown};
       
    79 public:
       
    80 	inline TSqlStatement(const TDesC& aSql,TResults& aResults);
       
    81 	TInt Execute(TDbTextComparison aTextComparison=EDbCompareNormal,
       
    82 		RDbRowSet::TAccess aAccess=RDbRowSet::EReadOnly,TBool aWindow=EFalse) const;
       
    83 private:
       
    84 	void ExecuteSql(TDbTextComparison aTextComparison) const;
       
    85 	void ExecuteQuery(RDbRowSet::TAccess aAccess,TBool aWindow) const;
       
    86 	TSqlType SqlType() const;
       
    87 private:
       
    88 	const TDesC& iSql;
       
    89 	TResults& iResults;
       
    90 	};
       
    91 
       
    92 class TScript
       
    93 	{
       
    94 public:
       
    95 	TScript();
       
    96 	~TScript()
       
    97 		{
       
    98 		iFile.Close();
       
    99 		}
       
   100 	TInt ReadNextStatement();
       
   101 	void GetNextTokenFromStatement(TDes& aToken);
       
   102 	void GetNextTokenFromLine(TDes& aToken);
       
   103 	TPtrC Statement();
       
   104 	TInt IntValue();
       
   105 	void WriteLine(const TDesC& aLine);
       
   106 	void WriteError(const TDesC& aLine);
       
   107 	void WriteSqlError(const TResults& aResults,const TDesC& aLine);
       
   108 	void WriteComment(const TDesC& aLine);
       
   109 	TKeyword Keyword(const TDesC& aKeyword) const;
       
   110 	void ConsumeLine();
       
   111 	void ConsumeStatement();
       
   112 	inline TInt LineNo() const;
       
   113 private:
       
   114 	TInt ReadNextLine();
       
   115 	TInt AppendNextLine();
       
   116 	TBool IsStatement();
       
   117 private:
       
   118 	TFileText iInput;
       
   119 	TFileText iOutput;
       
   120 	TScriptLine iBuf;
       
   121 	TLex iStatement;
       
   122 	TLex iLine;
       
   123 	TInt iLineNo;
       
   124 	RFile iFile;
       
   125 	};
       
   126 
       
   127 class TScriptEngine
       
   128 	{
       
   129 public:
       
   130 	inline TScriptEngine();
       
   131 	void RunL();
       
   132 private:
       
   133 	void ExecuteL();
       
   134 	TInt ExecuteScriptL();
       
   135 	TInt ExecuteSql(const TDesC& aSql);
       
   136 	TInt ExecuteSql();
       
   137 	// keyword operations
       
   138 	void DoPrintL();
       
   139 	void DoComment();
       
   140 	void DoError();
       
   141 	void DoEcho();
       
   142 	void DoWindow();
       
   143 	void DoAccess();
       
   144 	void DoRows();
       
   145 	void DoCompareL();
       
   146 	void DoPopulate();
       
   147 	void DoResultsL();
       
   148 	void DoBuildTable();
       
   149 	void DoQuery();
       
   150 	void DoTextComparison(TKeyword aKeyword);
       
   151 	void DoStartTimer();
       
   152 	void DoStopTimer();
       
   153 	void DoLoadDb();
       
   154 	//
       
   155 	void PrintL(RDbRowSet& aRowSet);
       
   156 	void CompareL(RDbRowSet& aRowSet);
       
   157 	void CompareValues(RDbRowSet& aRowSet,TDbColNo ColNo,TDbColType aType,const TDesC& aToken);
       
   158 	void FatalError(const TDesC& aLine);
       
   159 	void FatalError();
       
   160 	void FatalSqlError(const TDesC& aLine);
       
   161 	void TestForNoError();
       
   162 private:
       
   163 	TScript iScript;
       
   164 	TResults iResults;
       
   165 	TDbTextComparison iTextComparison;
       
   166 	TTimer iTimer;
       
   167 	TBool iEcho;
       
   168 	TBool iWindow;
       
   169 	RDbRowSet::TAccess iAccess;
       
   170 
       
   171 	};
       
   172 
       
   173 //
       
   174 // class TTimer
       
   175 //
       
   176 
       
   177 inline TTimer::TTimer(TScript& aScript)
       
   178 	: iScript(aScript)
       
   179 	{}
       
   180 
       
   181 void TTimer::Start(const TDesC& aDes)
       
   182 	{
       
   183 	TScriptLine line;
       
   184 	line.Format(_L("%S: "),&aDes);
       
   185 	iScript.WriteLine(line);
       
   186 	iTicks=User::TickCount();
       
   187 	}
       
   188 
       
   189 void TTimer::Stop(const TDesC& aDes)
       
   190 	{
       
   191 	TScriptLine line;
       
   192 	line.Format(_L("%S: "),&aDes);
       
   193 #ifdef __EPOC32__
       
   194 #define TICK_TIME 15625
       
   195 #else
       
   196 #define	TICK_TIME 100000
       
   197 #endif
       
   198 	TInt microSec=(User::TickCount()-iTicks)*TICK_TIME;
       
   199 	TUint sec=microSec/1000000;
       
   200 	TUint centi=(microSec/10000)-sec*100;
       
   201 	line.AppendFormat(_L("%u.%02us\n"),sec,centi);
       
   202 	iScript.WriteLine(line);
       
   203 	}
       
   204 
       
   205 ///////////////////////////////////////////////////////////////////////////////////////
       
   206 
       
   207 LOCAL_C void DeleteDataFile(const TDesC& aFullName)
       
   208     {
       
   209     RFs fsSession;
       
   210     TInt err = fsSession.Connect();
       
   211     if(err == KErrNone)
       
   212         {
       
   213         TEntry entry;
       
   214         if(fsSession.Entry(aFullName, entry) == KErrNone)
       
   215             {
       
   216             RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
       
   217             err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
       
   218             if(err != KErrNone)
       
   219                 {
       
   220                 RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
       
   221                 }
       
   222             err = fsSession.Delete(aFullName);
       
   223             if(err != KErrNone)
       
   224                 {
       
   225                 RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
       
   226                 }
       
   227             }
       
   228         fsSession.Close();
       
   229         }
       
   230     else
       
   231         {
       
   232         RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
       
   233         }
       
   234     }
       
   235 
       
   236 ///////////////////////////////////////////////////////////////////////////////////////
       
   237 ///////////////////////////////////////////////////////////////////////////////////////
       
   238 //Tests macros and functions.
       
   239 //If (!aValue) then the test will be panicked, the test data files will be deleted.
       
   240 static void Check(TInt aValue, TInt aLine)
       
   241     {
       
   242     if(!aValue)
       
   243         {
       
   244         RDebug::Print(_L("*** Expression evaluated to false\r\n"));
       
   245         DeleteDataFile(KTestDatabase);
       
   246         DeleteDataFile(KOutputFile);
       
   247         TheTest(EFalse, aLine);
       
   248         }
       
   249     }
       
   250 //If (aValue != aExpected) then the test will be panicked, the test data files will be deleted.
       
   251 static void Check(TInt aValue, TInt aExpected, TInt aLine)
       
   252     {
       
   253     if(aValue != aExpected)
       
   254         {
       
   255         RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
   256         DeleteDataFile(KTestDatabase);
       
   257         DeleteDataFile(KOutputFile);
       
   258         TheTest(EFalse, aLine);
       
   259         }
       
   260     }
       
   261 //Use these to test conditions.
       
   262 #define TEST(arg) Check((arg), __LINE__)
       
   263 #define TEST2(aValue, aExpected) Check(aValue, aExpected, __LINE__)
       
   264 
       
   265 ///////////////////////////////////////////////////////////////////////////////////////
       
   266 ///////////////////////////////////////////////////////////////////////////////////////
       
   267 
       
   268 //
       
   269 // class TResults
       
   270 //
       
   271 
       
   272 inline TResults::TResults()
       
   273 	: iView(TheView),iError(KErrNone)
       
   274 	{}
       
   275 
       
   276 
       
   277 //
       
   278 // class TSqlStatement
       
   279 //
       
   280 
       
   281 inline TSqlStatement::TSqlStatement(const TDesC& aSql,TResults& aResults)
       
   282 	: iSql(aSql),iResults(aResults)
       
   283 	{}
       
   284 
       
   285 //
       
   286 // executes DML or DDL
       
   287 //
       
   288 void TSqlStatement::ExecuteSql(TDbTextComparison aTextComparison) const
       
   289 	{
       
   290 	TInt r=TheDatabase.Execute(iSql,aTextComparison);
       
   291 	if (r<0)
       
   292 		iResults.iError=r;
       
   293 	else
       
   294 		{
       
   295 		iResults.iError=KErrNone;
       
   296 		iResults.iRows=r;
       
   297 		}
       
   298 	}
       
   299 
       
   300 void TSqlStatement::ExecuteQuery(RDbRowSet::TAccess aAccess,TBool aWindow) const
       
   301 	{
       
   302 	iResults.iView.Close();			// discard any previous queries
       
   303 	TInt& err=iResults.iError;
       
   304 	if (aWindow)
       
   305 		err=iResults.iView.Prepare(TheDatabase,iSql,KDbUnlimitedWindow,aAccess);
       
   306 	else
       
   307 		err=iResults.iView.Prepare(TheDatabase,iSql,aAccess);
       
   308 	if (err==KErrNone)
       
   309 		err=iResults.iView.EvaluateAll();
       
   310 	}
       
   311 
       
   312 //
       
   313 // determines the type of sql statement by matching keywords
       
   314 //
       
   315 TSqlStatement::TSqlType TSqlStatement::SqlType() const
       
   316 	{
       
   317 	for (TUint i=0;i<ARRAY_SIZE(KDDLKeywords);++i)
       
   318 		{
       
   319 		if (iSql.FindF(KDDLKeywords[i])==0)
       
   320 			return EDDL;
       
   321 		}
       
   322 	for (TUint ii=0;ii<ARRAY_SIZE(KDMLKeywords);++ii)
       
   323 		{
       
   324 		if (iSql.FindF(KDMLKeywords[ii])==0)
       
   325 			return EDML;
       
   326 		}
       
   327 	for (TUint j=0;j<ARRAY_SIZE(KQueryKeywords);++j)
       
   328 		{
       
   329 		if (iSql.FindF(KQueryKeywords[j])==0)
       
   330 			return EQuery;
       
   331 		}
       
   332 	return EUnknown;
       
   333 	}
       
   334 
       
   335 //
       
   336 // executes the sql statement
       
   337 //
       
   338 TInt TSqlStatement::Execute(TDbTextComparison aTextComparison,RDbRowSet::TAccess aAccess,TBool aWindow) const
       
   339 	{
       
   340 	TInt r=KErrNone;
       
   341 	switch (SqlType())
       
   342 		{
       
   343 	case EDDL:
       
   344 	case EDML:
       
   345 		ExecuteSql(aTextComparison);
       
   346 		break;
       
   347 	case EQuery:
       
   348 		ExecuteQuery(aAccess,aWindow);
       
   349 		break;
       
   350 	case EUnknown:
       
   351 	default:
       
   352 		r=KErrNotFound;
       
   353 		break;
       
   354 		}
       
   355 	return r;
       
   356 	}
       
   357 
       
   358 
       
   359 //
       
   360 // class TScript
       
   361 //
       
   362 
       
   363 TScript::TScript()
       
   364 	: iLineNo(0)
       
   365 	{
       
   366 	TheTest.Printf(_L("---TScript::TScript(), Open the script file \"%S\"\r\n"), &KRomScriptFile);
       
   367 	RFile file;
       
   368 	TInt r=file.Open(TheFs, KRomScriptFile, EFileRead);
       
   369 	TEST2(r, KErrNone);
       
   370 	iInput.Set(file);
       
   371     TheTest.Printf(_L("---TScript::TScript(), Create the file \"%S\"\r\n"), &KOutputFile);
       
   372 	TEST2(file.Replace(TheFs, KOutputFile, EFileWrite), KErrNone);
       
   373 	iOutput.Set(file);
       
   374 	iFile = file;
       
   375 	}
       
   376 
       
   377 inline TInt TScript::LineNo() const
       
   378 	{return iLineNo;}
       
   379 
       
   380 //
       
   381 //  checks for keywords which possibly conform to the usual statement format (ie end in ';')
       
   382 //
       
   383 TBool TScript::IsStatement()
       
   384 	{
       
   385 	if (iLine.Remainder().Length()==0)	// null statement
       
   386 		return ETrue;
       
   387 	TPtrC line=iLine.Remainder();
       
   388 	TKeyword keyword=Keyword(line);
       
   389 	switch (keyword)
       
   390 		{
       
   391 	case EPrint:
       
   392 	case ERows:
       
   393 	case EBuild:
       
   394 	case EError:
       
   395 	case EQuery:
       
   396 	case ENormal:
       
   397 	case EFolded:
       
   398 	case ECollated:
       
   399 	case EStart:
       
   400 	case EStop:
       
   401 	case ELoad:
       
   402 	case EEcho:
       
   403 	case EWindow:
       
   404 	case EAccess:
       
   405 	case EUnknown:						// could be sql
       
   406 		return ETrue;
       
   407 	case EComment:
       
   408 	case EPopulate:
       
   409 	case ECompare:
       
   410 	case EResults:
       
   411 		iStatement=line;				// not a statement, so make it the whole line
       
   412 		return EFalse;
       
   413 	default:
       
   414 		TEST(0);
       
   415 		return EFalse;
       
   416 		}
       
   417 	}
       
   418 
       
   419 //
       
   420 // reads the next non-blank statement or line
       
   421 //
       
   422 TInt TScript::ReadNextStatement()
       
   423 	{
       
   424 	TInt r=ReadNextLine();
       
   425 	if (r!=KErrNone || !IsStatement())
       
   426 		return r;
       
   427 	TChar c=0;
       
   428 	while (c!=';')
       
   429 		{
       
   430 		c=iLine.Get();
       
   431 		if (!c)							// nothing left to read
       
   432 			{
       
   433 			r=AppendNextLine();
       
   434 			if (r!=KErrNone)
       
   435 				return r;
       
   436 			}
       
   437 		}
       
   438 	iLine.UnGet();						// the semi-colon
       
   439 	iStatement=iLine.MarkedToken();
       
   440 	iLine.Get();						// the semi-colon
       
   441 	iLine.SkipSpaceAndMark();
       
   442 	return KErrNone;
       
   443 	}
       
   444 
       
   445 TPtrC TScript::Statement()
       
   446 	{
       
   447 	return iStatement.Remainder();
       
   448 	}
       
   449 
       
   450 void TScript::ConsumeLine()
       
   451 	{
       
   452 	iLine=TPtrC();
       
   453 	iStatement=TPtrC();
       
   454 	}
       
   455 
       
   456 void TScript::ConsumeStatement()
       
   457 	{
       
   458 	iLine=iLine.Remainder();
       
   459 	iStatement=TPtrC();
       
   460 	}
       
   461 
       
   462 //
       
   463 // reads the next non-blank line into iLine
       
   464 //
       
   465 TInt TScript::ReadNextLine()
       
   466 	{
       
   467 	while (iLine.Remainder().Length()==0)
       
   468 		{
       
   469 		TInt r=iInput.Read(iBuf);
       
   470 		if (r!=KErrNone)
       
   471 			return r;
       
   472 		if (iBuf.Length()>0 && iBuf[0]==0xfeff)	// unicode stream marker
       
   473 			iBuf.Delete(0,1);
       
   474 		iLineNo++;
       
   475 		iLine=iBuf;
       
   476 		iLine.SkipSpaceAndMark();
       
   477 		}
       
   478 	return KErrNone;
       
   479 	}
       
   480 
       
   481 //
       
   482 // adds next line from file to iLine
       
   483 //
       
   484 TInt TScript::AppendNextLine()
       
   485 	{
       
   486 	TScriptLine line;
       
   487 	do {
       
   488 		TInt r=iInput.Read(line);
       
   489 		if (r!=KErrNone)
       
   490 			return r;
       
   491 		iLineNo++;
       
   492 		} while (line.Length()==0);
       
   493 	iBuf=iLine.MarkedToken();
       
   494 	iBuf.Append(line);
       
   495 	iLine=iBuf;
       
   496 	return KErrNone;
       
   497 	}
       
   498 
       
   499 void TScript::WriteError(const TDesC& aLine)
       
   500 	{
       
   501 	TScriptLine line;
       
   502 	line.Format(_L("Error at line %d: %S\n"),iLineNo,&aLine);
       
   503 	WriteLine(line);
       
   504 	TheTest.Printf(line);
       
   505 	}
       
   506 
       
   507 void TScript::WriteSqlError(const TResults& aResults,const TDesC& aLine)
       
   508 	{
       
   509 	TScriptLine line;
       
   510 	line.Format(_L("Error at line %d: %S :-\n"),aResults.iLineNo,&aLine);
       
   511 	WriteLine(line);
       
   512 	TheTest.Printf(line);
       
   513 	line.Format(_L("\t%S\n"),&aResults.iLine);
       
   514 	WriteLine(line);
       
   515 	TheTest.Printf(line);
       
   516 	}
       
   517 
       
   518 void TScript::WriteLine(const TDesC& aLine)
       
   519 	{
       
   520 	TScriptLine l=aLine;
       
   521 	l.Append('\r');
       
   522 	iOutput.Write(l);
       
   523 	}
       
   524 
       
   525 void TScript::WriteComment(const TDesC& aLine)
       
   526 	{
       
   527 	TScriptLine line;
       
   528 	line.Format(_L("\n%S"),&aLine);
       
   529 	WriteLine(line);
       
   530 	}
       
   531 
       
   532 //
       
   533 // returns the integer n from the ' = n ' which must follow in the statement
       
   534 //
       
   535 TInt TScript::IntValue()
       
   536 	{
       
   537 	TScriptToken keyword;
       
   538 	GetNextTokenFromStatement(keyword);
       
   539 	if (keyword.Compare(_L("="))!=0)
       
   540 		WriteError(_L("expected '=' missing"));
       
   541 	iStatement.SkipSpaceAndMark();
       
   542 	TInt num=0;
       
   543 	TInt err=iStatement.Val(num);
       
   544 	if (err!=KErrNone)
       
   545 		WriteError(_L("expected number missing"));
       
   546 	return num;
       
   547 	}
       
   548 
       
   549 TKeyword TScript::Keyword(const TDesC& aKeyword) const
       
   550 	{
       
   551 	for (TInt ii=0; ii<ENumKeywords; ++ii)
       
   552 		{
       
   553 		if (aKeyword.FindF(KScriptKeywords[ii])==0)
       
   554 			return TKeyword(ii);
       
   555 		}
       
   556 	return EUnknown;
       
   557 	}
       
   558 
       
   559 //
       
   560 // gets the next token from iStatement
       
   561 //
       
   562 void TScript::GetNextTokenFromStatement(TDes& aToken)
       
   563 	{
       
   564 	iStatement.SkipSpaceAndMark();
       
   565 	TUint c;
       
   566 	do
       
   567 		{
       
   568 		c=iStatement.Get();
       
   569 		if (c=='=' || c=='!')
       
   570 			break;
       
   571 		} while (iStatement.Peek().IsAlphaDigit());
       
   572 	aToken=iStatement.MarkedToken();
       
   573 	iStatement.SkipSpaceAndMark();
       
   574 	}
       
   575 
       
   576 //
       
   577 // gets the next token from iLine
       
   578 //
       
   579 void TScript::GetNextTokenFromLine(TDes& aToken)
       
   580 	{
       
   581 	iLine.SkipSpaceAndMark();
       
   582 	TUint c=0;
       
   583 	TChar cc=c;
       
   584 	TBool literal=EFalse;
       
   585 	do
       
   586 		{
       
   587 		c=iLine.Get();
       
   588 		if (!c)
       
   589 			{
       
   590 			AppendNextLine();
       
   591 			iLine.SkipSpaceAndMark();
       
   592 			c=iLine.Get();
       
   593 			}
       
   594 		if (c=='\'' || c=='#')
       
   595 			literal=!literal;
       
   596 		if ((c==',' || c=='(' || c==')' || c=='{' || c=='}' || c=='!' ) && !literal)
       
   597 			break;
       
   598 		cc=iLine.Peek();
       
   599 		} while (cc.IsAlphaDigit() || literal || TUint(cc)=='.' || TUint(cc)=='+' || TUint(cc)=='-');
       
   600 	aToken=iLine.MarkedToken();
       
   601 	if (TUint(cc)==';')					// ignore semi-colons - they're optional
       
   602 		iLine.Get();
       
   603 	iLine.SkipSpaceAndMark();
       
   604 	if (c=='!')
       
   605 		{
       
   606 		iStatement=iLine.Remainder();
       
   607 		TPtrC comment=iStatement.Remainder();
       
   608 		WriteComment(comment);
       
   609 		iLine=TPtrC();
       
   610 		GetNextTokenFromLine(aToken);
       
   611 		}
       
   612 	}
       
   613 
       
   614 
       
   615 //
       
   616 // class TScriptEngine
       
   617 //
       
   618 
       
   619 TScriptEngine::TScriptEngine()
       
   620 	: iTextComparison(EDbCompareNormal),iTimer(iScript),iEcho(EFalse),iWindow(EFalse),iAccess(RDbRowSet::EReadOnly)
       
   621 	{}
       
   622 
       
   623 
       
   624 //
       
   625 // runs the script file
       
   626 //
       
   627 void TScriptEngine::RunL()
       
   628 	{
       
   629 	while (iScript.ReadNextStatement()!=KErrEof)
       
   630 		ExecuteL();
       
   631 	TestForNoError();
       
   632 	}
       
   633 
       
   634 void TScriptEngine::TestForNoError()
       
   635 	{
       
   636 	if (iResults.iError!=KErrNone)
       
   637 		{
       
   638 		TScriptLine line;
       
   639 		line.Format(_L("unexpected error %d"),iResults.iError);
       
   640 		FatalSqlError(line);
       
   641 		}
       
   642 	}
       
   643 
       
   644 void TScriptEngine::ExecuteL()
       
   645 	{
       
   646 	if (ExecuteScriptL()!=KErrNone && ExecuteSql()!=KErrNone)
       
   647 		FatalSqlError(_L("syntax error"));
       
   648 	}
       
   649 
       
   650 TInt TScriptEngine::ExecuteScriptL()
       
   651 	{
       
   652 	TKeyword keyword=iScript.Keyword(iScript.Statement());
       
   653 	if (keyword!=EError)
       
   654 		TestForNoError();
       
   655 	switch (keyword)
       
   656 		{
       
   657 	case EPrint:
       
   658 		DoPrintL();
       
   659 		break;
       
   660 	case ERows:
       
   661 		DoRows();
       
   662 		break;
       
   663 	case ELoad:
       
   664 		DoLoadDb();
       
   665 		break;
       
   666 	case EEcho:
       
   667 		DoEcho();
       
   668 		break;
       
   669 	case EWindow:
       
   670 		DoWindow();
       
   671 		break;
       
   672 	case EAccess:
       
   673 		DoAccess();
       
   674 		break;
       
   675 	case ECompare:
       
   676 		DoCompareL();
       
   677 		break;
       
   678 	case EError:
       
   679 		DoError();
       
   680 		break;
       
   681 	case EPopulate:
       
   682 		DoPopulate();
       
   683 		break;
       
   684 	case EComment:
       
   685 		DoComment();
       
   686 		break;
       
   687 	case EResults:
       
   688 		DoResultsL();
       
   689 		break;
       
   690 	case EBuild:
       
   691 		DoBuildTable();
       
   692 		break;
       
   693 	case EQuery:
       
   694 		DoQuery();
       
   695 		break;
       
   696 	case ENormal:
       
   697 	case EFolded:
       
   698 	case ECollated:
       
   699 		DoTextComparison(keyword);
       
   700 		break;
       
   701 	case EStart:
       
   702 		DoStartTimer();
       
   703 		break;
       
   704 	case EStop:
       
   705 		DoStopTimer();
       
   706 		break;
       
   707 	case EUnknown:
       
   708 	default:
       
   709 		return KErrNotFound;
       
   710 		}
       
   711 	return KErrNone;
       
   712 	}
       
   713 
       
   714 TInt TScriptEngine::ExecuteSql()
       
   715 	{
       
   716 	return ExecuteSql(iScript.Statement());
       
   717 	}
       
   718 
       
   719 TInt TScriptEngine::ExecuteSql(const TDesC& aSql)
       
   720 	{
       
   721 	if (iEcho)
       
   722 		{
       
   723 		TScriptLine line(_L("\nSQL:\t"));
       
   724 		line.Append(aSql);
       
   725 		iScript.WriteLine(line);
       
   726 		}
       
   727 	iResults.iLineNo=iScript.LineNo();
       
   728 	iResults.iLine=aSql;
       
   729 	TSqlStatement statement(aSql,iResults);
       
   730 	return statement.Execute(iTextComparison,iAccess,iWindow);
       
   731 	}
       
   732 
       
   733 void TScriptEngine::DoStartTimer()
       
   734 	{
       
   735 	// test its right function
       
   736 	TScriptToken keyword;
       
   737 	iScript.GetNextTokenFromStatement(keyword);
       
   738 	TEST2(keyword.CompareF(_L("START")), 0);
       
   739 	iScript.GetNextTokenFromStatement(keyword);
       
   740 	TEST2(keyword.CompareF(_L("TIMER")), 0);
       
   741 	//
       
   742 	iTimer.Start(_L("Timer started"));
       
   743 	}
       
   744 
       
   745 void TScriptEngine::DoStopTimer()
       
   746 	{
       
   747 	// test its right function
       
   748 	TScriptToken keyword;
       
   749 	iScript.GetNextTokenFromStatement(keyword);
       
   750 	TEST2(keyword.CompareF(_L("STOP")), 0);
       
   751 	iScript.GetNextTokenFromStatement(keyword);
       
   752 	TEST2(keyword.CompareF(_L("TIMER")), 0);
       
   753 	//
       
   754 	iTimer.Stop(_L("Timer stopped"));
       
   755 	}
       
   756 
       
   757 void TScriptEngine::DoTextComparison(TKeyword aKeyword)
       
   758 	{
       
   759 	TPtrC line;
       
   760 	switch (aKeyword)
       
   761 		{
       
   762 	case ENormal:
       
   763 		iTextComparison=EDbCompareNormal;
       
   764 		line.Set(_L("[Normal text comparison]"));
       
   765 		break;
       
   766 	case EFolded:
       
   767 		iTextComparison=EDbCompareFolded;
       
   768 		line.Set(_L("[Folded text comparison]"));
       
   769 		break;
       
   770 	case ECollated:
       
   771 		iTextComparison=EDbCompareCollated;
       
   772 		line.Set(_L("[Collated text comparison]"));
       
   773 		break;
       
   774 	default:
       
   775 		TEST(0);
       
   776 		}
       
   777 	iScript.WriteLine(line);
       
   778 	}
       
   779 
       
   780 void TScriptEngine::DoComment()
       
   781 	{
       
   782 	// test its right function
       
   783 	TScriptToken keyword;
       
   784 	iScript.GetNextTokenFromStatement(keyword);
       
   785 	TEST2(keyword.CompareF(_L("!")), 0);
       
   786 	//
       
   787 	TPtrC comment=iScript.Statement();
       
   788 	iScript.WriteComment(comment);
       
   789 	iScript.ConsumeLine();
       
   790 	}
       
   791 
       
   792 void TScriptEngine::DoError()
       
   793 	{
       
   794 	// test its right function
       
   795 	TScriptToken keyword;
       
   796 	iScript.GetNextTokenFromStatement(keyword);
       
   797 	TEST2(keyword.CompareF(_L("ERROR")), 0);
       
   798 	//
       
   799 	TScriptLine line;
       
   800 	if (iScript.Statement().Length()==0)
       
   801 		{
       
   802 		if (iResults.iError>=0)
       
   803 			FatalSqlError(_L("no error when one was expected"));
       
   804 		line=_L("\t\tERROR OK");
       
   805 		}
       
   806 	else
       
   807 		{
       
   808 		TInt err=iScript.IntValue();
       
   809 		if (iResults.iError!=err)
       
   810 			{
       
   811 			line.Format(_L("expected error %d, actual error %d"),err,iResults.iError);
       
   812 			FatalSqlError(line);
       
   813 			}
       
   814 		line.Format(_L("\t\tERROR=%D OK"),err);
       
   815 		}
       
   816 	iResults.iError=0;
       
   817 	iScript.WriteLine(line);
       
   818 	}
       
   819 
       
   820 void TScriptEngine::DoRows()
       
   821 	{
       
   822 	// test its right function
       
   823 	TScriptToken keyword;
       
   824 	iScript.GetNextTokenFromStatement(keyword);
       
   825 	TEST2(keyword.CompareF(_L("ROWS")), 0);
       
   826 	//
       
   827 	TScriptLine line;
       
   828 	TInt rows=iScript.IntValue();
       
   829 	if (iResults.iRows!=rows)
       
   830 		{
       
   831 		line.Format(_L("expected rows %d, actual rows %d"),rows,iResults.iRows);
       
   832 		FatalSqlError(line);
       
   833 		}
       
   834 	line.Format(_L("\t\tROWS=%D OK"),rows);
       
   835 	iScript.WriteLine(line);
       
   836 	}
       
   837 
       
   838 void TScriptEngine::DoLoadDb()
       
   839 	{
       
   840 	// test its right function
       
   841 	TScriptToken token;
       
   842 	iScript.GetNextTokenFromStatement(token);
       
   843 	TEST2(token.CompareF(_L("LOAD")), 0);
       
   844 	//
       
   845 	TFileName database(iScript.Statement());
       
   846 	TheDatabase.Close();
       
   847 	TScriptLine line;
       
   848 	line.Format(_L("Opening database: %S"),&database);
       
   849 	iScript.WriteLine(line);
       
   850 	TEST2(TheDatabase.Open(TheFs,database), KErrNone);
       
   851 	}
       
   852 
       
   853 void TScriptEngine::DoEcho()
       
   854 	{
       
   855 	// test its right function
       
   856 	TScriptToken keyword;
       
   857 	iScript.GetNextTokenFromStatement(keyword);
       
   858 	TEST2(keyword.CompareF(_L("ECHO")), 0);
       
   859 	//
       
   860 	iScript.GetNextTokenFromStatement(keyword);
       
   861 	if (keyword.CompareF(_L("OFF"))==0)
       
   862 		{
       
   863 		iEcho=EFalse;
       
   864 		iScript.WriteLine(_L("Echo is off"));
       
   865 		}
       
   866 	else if (keyword.CompareF(_L("ON"))==0)
       
   867 		{
       
   868 		iEcho=ETrue;
       
   869 		iScript.WriteLine(_L("Echo is on"));
       
   870 		}
       
   871 	else
       
   872 		FatalError(_L("Expected ON|OFF to follow ECHO statement"));
       
   873 	}
       
   874 
       
   875 void TScriptEngine::DoWindow()
       
   876 	{
       
   877 	// test its right function
       
   878 	TScriptToken keyword;
       
   879 	iScript.GetNextTokenFromStatement(keyword);
       
   880 	TEST2(keyword.CompareF(_L("WINDOW")), 0);
       
   881 	//
       
   882 	iScript.GetNextTokenFromStatement(keyword);
       
   883 	if (keyword.CompareF(_L("OFF"))==0)
       
   884 		{
       
   885 		iWindow=EFalse;
       
   886 		iScript.WriteLine(_L("Window is off"));
       
   887 		}
       
   888 	else if (keyword.CompareF(_L("ON"))==0)
       
   889 		{
       
   890 		iWindow=ETrue;
       
   891 		iScript.WriteLine(_L("Window is on"));
       
   892 		}
       
   893 	else
       
   894 		FatalError(_L("Expected ON|OFF to follow WINDOW statement"));
       
   895 	}
       
   896 
       
   897 void TScriptEngine::DoAccess()
       
   898 	{
       
   899 	// test its right function
       
   900 	TScriptToken keyword;
       
   901 	iScript.GetNextTokenFromStatement(keyword);
       
   902 	TEST2(keyword.CompareF(_L("ACCESS")), 0);
       
   903 	//
       
   904 	iScript.GetNextTokenFromStatement(keyword);
       
   905 	if (keyword.CompareF(_L("UPDATE"))==0)
       
   906 		{
       
   907 		iAccess=RDbRowSet::EUpdatable;
       
   908 		iScript.WriteLine(_L("Access is updateable"));
       
   909 		}
       
   910 	else if (keyword.CompareF(_L("READ"))==0)
       
   911 		{
       
   912 		iAccess=RDbRowSet::EReadOnly;
       
   913 		iScript.WriteLine(_L("Access is read only"));
       
   914 		}
       
   915 	else if (keyword.CompareF(_L("INSERT"))==0)
       
   916 		{
       
   917 		iAccess=RDbRowSet::EInsertOnly;
       
   918 		iScript.WriteLine(_L("Access is insert only"));
       
   919 		}
       
   920 	else
       
   921 		FatalError(_L("Expected UPDATE|INSERT|READ to follow ACCESS statement"));
       
   922 	}
       
   923 
       
   924 void TScriptEngine::DoResultsL()
       
   925 	{
       
   926 	// test its right function
       
   927 	TScriptToken token;
       
   928 	iScript.GetNextTokenFromLine(token);
       
   929 	TEST2(token.CompareF(_L("RESULTS")), 0);
       
   930 	//
       
   931 	iScript.GetNextTokenFromLine(token);
       
   932 	if (token.Compare(_L("{"))!=0)
       
   933 		FatalError(_L("missing '{'"));
       
   934 	iScript.GetNextTokenFromLine(token);					// first value
       
   935 	TLex value;
       
   936 	RDbRowSet& rowset=iResults.iView;
       
   937 	CDbColSet* colset=rowset.ColSetL();
       
   938 	CleanupStack::PushL(colset);
       
   939 	TDbColNo colno=colset->ColNo(KRowIdColName);
       
   940 	CArrayFixFlat<TInt>* rowIdScript=new CArrayFixFlat<TInt>(4);
       
   941 	CleanupStack::PushL(rowIdScript);
       
   942 	CArrayFixFlat<TInt>* rowIdView=new CArrayFixFlat<TInt>(4);
       
   943 	CleanupStack::PushL(rowIdView);
       
   944 	rowset.BeginningL();
       
   945 	while (rowset.NextL())
       
   946 		{
       
   947 		rowset.GetL();
       
   948 		TUint rIdScript;
       
   949 		value=token;
       
   950 		if (value.Val(rIdScript)!=KErrNone)
       
   951 			{
       
   952 			TScriptLine line;
       
   953 			line.Format(_L("Unable to extract row id from \"%S\""),&token);
       
   954 			FatalError(line);
       
   955 			}
       
   956 		TUint rIdView=rowset.ColUint(colno);
       
   957 		rowIdScript->AppendL(rIdScript);
       
   958 		rowIdView->AppendL(rIdView);
       
   959 		iScript.GetNextTokenFromLine(token);
       
   960 		if (token.Compare(_L(","))==0 || token.Compare(_L("}"))==0)
       
   961 			{
       
   962 			if (rowIdScript->Count())
       
   963 				{
       
   964 				TKeyArrayFix key(0,ECmpTInt);
       
   965 				rowIdScript->Sort(key);
       
   966 				rowIdView->Sort(key);
       
   967 				for (TInt ii=0;ii<rowIdScript->Count();++ii)
       
   968 					{
       
   969 					TInt expectedId=(*rowIdScript)[ii];
       
   970 					TInt actualId=(*rowIdView)[ii];
       
   971 					if (actualId!=expectedId)
       
   972 						{
       
   973 						TScriptLine line;
       
   974 						line.Format(_L("expected row id %d, actual row id %d"),actualId,expectedId);
       
   975 						FatalError(line);
       
   976 						}
       
   977 					}
       
   978 				rowIdScript->Reset();
       
   979 				rowIdView->Reset();
       
   980 				}
       
   981 			if (token.Compare(_L(","))==0)
       
   982 				iScript.GetNextTokenFromLine(token);
       
   983 			}
       
   984 		}
       
   985 	if (token.Compare(_L("}"))!=0)
       
   986 		FatalError(_L("too many results expected"));
       
   987 	CleanupStack::PopAndDestroy(3);	// arrays + colset
       
   988 	iScript.ConsumeStatement();
       
   989 	}
       
   990 
       
   991 //
       
   992 // same as Sql create statement, but adds a counter
       
   993 //
       
   994 void TScriptEngine::DoBuildTable()
       
   995 	{
       
   996 	// test its right function
       
   997 	TScriptToken keyword;
       
   998 	iScript.GetNextTokenFromStatement(keyword);
       
   999 	TEST2(keyword.CompareF(_L("BUILD")), 0);
       
  1000 	//
       
  1001 	TScriptLine sql(_L("CREATE "));
       
  1002 	sql.Append(iScript.Statement());
       
  1003 	TInt pos=sql.Find(_L("("));
       
  1004 	sql.Insert(++pos,_L("Rw COUNTER,"));
       
  1005 	iScript.ConsumeStatement();
       
  1006 	ExecuteSql(sql);
       
  1007 	}
       
  1008 
       
  1009 //
       
  1010 // same as Sql select statement, but makes sure counter is included
       
  1011 //
       
  1012 void TScriptEngine::DoQuery()
       
  1013 	{
       
  1014 	// test its right function
       
  1015 	TScriptToken keyword;
       
  1016 	iScript.GetNextTokenFromStatement(keyword);
       
  1017 	TEST2(keyword.CompareF(_L("QUERY")), 0);
       
  1018 	//
       
  1019 	TScriptLine sql(iScript.Statement());
       
  1020 	if (sql.Find(_L("*"))!=0)
       
  1021 		{
       
  1022 		sql.Insert(0,_L(","));
       
  1023 		sql.Insert(0,KRowIdColName);
       
  1024 		}
       
  1025 	sql.Insert(0,_L("SELECT "));
       
  1026 	iScript.ConsumeStatement();
       
  1027 	ExecuteSql(sql);
       
  1028 	}
       
  1029 
       
  1030 void TScriptEngine::FatalError(const TDesC& aLine)
       
  1031 	{
       
  1032 	iScript.WriteError(aLine);
       
  1033 	TEST(0);
       
  1034 	}
       
  1035 
       
  1036 void TScriptEngine::FatalError()
       
  1037 	{
       
  1038 	FatalError(_L("wrong expected value"));
       
  1039 	}
       
  1040 
       
  1041 void TScriptEngine::FatalSqlError(const TDesC& aLine)
       
  1042 	{
       
  1043 	iScript.WriteSqlError(iResults,aLine);
       
  1044 	TEST(0);
       
  1045 	}
       
  1046 
       
  1047 void TScriptEngine::DoPopulate()
       
  1048 	{
       
  1049 	// check its right function
       
  1050 	TScriptToken token;
       
  1051 	iScript.GetNextTokenFromLine(token);
       
  1052 	TEST2(token.CompareF(_L("POPULATE")), 0);
       
  1053 	//
       
  1054 	TScriptLine sqlbase=_L("INSERT INTO ");
       
  1055 	iScript.GetNextTokenFromLine(token);	// table name
       
  1056 	sqlbase.AppendFormat(_L("%S "),&token);
       
  1057 	iScript.GetNextTokenFromLine(token);
       
  1058 	if (token.Compare(_L("("))==0)			// optional column names present?
       
  1059 		{
       
  1060 		for (;;)
       
  1061 			{
       
  1062 			sqlbase.AppendFormat(token);
       
  1063 			if (token.Compare(_L(")"))==0)
       
  1064 				break;
       
  1065 			iScript.GetNextTokenFromLine(token);
       
  1066 			}
       
  1067 		iScript.GetNextTokenFromLine(token);
       
  1068 		}
       
  1069 	if (token.Compare(_L("{"))!=0)
       
  1070 		FatalError(_L("missing '{'"));
       
  1071 	sqlbase.AppendFormat(_L(" VALUES ("));
       
  1072 	iScript.GetNextTokenFromLine(token);	// first value
       
  1073 	TheDatabase.Begin();					// all in same transaction
       
  1074 	for (;;)
       
  1075 		{
       
  1076 		if (token.Compare(_L("}"))==0)
       
  1077 			break;
       
  1078 		TScriptLine sql=sqlbase;
       
  1079 		for (;;)
       
  1080 			{
       
  1081 			sql.Append(token);
       
  1082 			iScript.GetNextTokenFromLine(token);
       
  1083 			if (token.Compare(_L(","))==0)
       
  1084 				{
       
  1085 				sql.Append(token);			// comma
       
  1086 				iScript.GetNextTokenFromLine(token);
       
  1087 				}
       
  1088 			else
       
  1089 				break;
       
  1090 			}
       
  1091 		sql.AppendFormat(_L(")"));
       
  1092 		ExecuteSql(sql);
       
  1093 		TestForNoError();
       
  1094 		}
       
  1095 	TheDatabase.Commit();
       
  1096 	iScript.ConsumeStatement();
       
  1097 	}
       
  1098 
       
  1099 void TScriptEngine::DoPrintL()
       
  1100 	{
       
  1101 	// check its right function
       
  1102 	TScriptToken keyword;
       
  1103 	iScript.GetNextTokenFromStatement(keyword);
       
  1104 	TEST2(keyword.CompareF(_L("PRINT")), 0);
       
  1105 	//
       
  1106 	iScript.GetNextTokenFromStatement(keyword);
       
  1107 	if (keyword.CompareF(_L("VIEW"))==0)
       
  1108 		PrintL(iResults.iView);
       
  1109 	else if (keyword.CompareF(_L("TABLE"))==0)
       
  1110 		{
       
  1111 		iScript.GetNextTokenFromStatement(keyword);	// name of table
       
  1112 		RDbTable table;
       
  1113 		TInt err=table.Open(TheDatabase,keyword,table.EReadOnly);
       
  1114 		if (err!=KErrNone)
       
  1115 			FatalError(_L("unable to open table"));
       
  1116 		PrintL(table);
       
  1117 		table.Close();
       
  1118 		}
       
  1119 	else
       
  1120 		FatalError(_L("expected VIEW or TABLE keyword not present"));
       
  1121 	}
       
  1122 
       
  1123 void TScriptEngine::DoCompareL()
       
  1124 	{
       
  1125 	// check its right function
       
  1126 	TScriptToken keyword;
       
  1127 	iScript.GetNextTokenFromLine(keyword);
       
  1128 	TEST2(keyword.CompareF(_L("COMPARE")), 0);
       
  1129 	//
       
  1130 	iScript.GetNextTokenFromLine(keyword);
       
  1131 	if (keyword.CompareF(_L("VIEW"))==0)
       
  1132 		CompareL(iResults.iView);
       
  1133 	else if (keyword.CompareF(_L("TABLE"))==0)
       
  1134 		{
       
  1135 		iScript.GetNextTokenFromLine(keyword);	// name of table
       
  1136 		RDbTable table;
       
  1137 		TInt err=table.Open(TheDatabase,keyword,table.EReadOnly);
       
  1138 		if (err!=KErrNone)
       
  1139 			FatalError(_L("unable to open table"));
       
  1140 		CompareL(table);
       
  1141 		table.Close();
       
  1142 		}
       
  1143 	else
       
  1144 		FatalError(_L("expected VIEW or TABLE keyword not present"));
       
  1145 	}
       
  1146 
       
  1147 void TScriptEngine::CompareL(RDbRowSet& aRowSet)
       
  1148 	{
       
  1149 	TScriptToken token;
       
  1150 	iScript.GetNextTokenFromLine(token);
       
  1151 	TBool rowIdMode=EFalse;
       
  1152 	CArrayFixFlat<TInt>* rowIdToTest=new CArrayFixFlat<TInt>(4);
       
  1153 	CleanupStack::PushL(rowIdToTest);
       
  1154 	if (token.Compare(_L("("))==0)				// optional row ids present?
       
  1155 		{
       
  1156 		rowIdMode=ETrue;
       
  1157 		iScript.GetNextTokenFromLine(token);	// first value
       
  1158 		TLex value;
       
  1159 		TInt rowId;
       
  1160 		for (;;)
       
  1161 			{
       
  1162 			value=token;
       
  1163 			TEST2(value.Val(rowId), KErrNone);
       
  1164 			rowIdToTest->AppendL(rowId);		// add row id to array
       
  1165 			iScript.GetNextTokenFromLine(token);
       
  1166 			if (token.Compare(_L(")"))==0)
       
  1167 				break;
       
  1168 			if (token.Compare(_L(","))==0)
       
  1169 				iScript.GetNextTokenFromLine(token);
       
  1170 			}
       
  1171 		iScript.GetNextTokenFromLine(token);
       
  1172 		}
       
  1173 	if (token.Compare(_L("{"))!=0)
       
  1174 		FatalError(_L("missing '{'"));
       
  1175 	TInt columns=aRowSet.ColCount();
       
  1176 	CDbColSet* colset=aRowSet.ColSetL();
       
  1177 	aRowSet.BeginningL();
       
  1178 	while (aRowSet.NextL())
       
  1179 		{
       
  1180 		aRowSet.GetL();
       
  1181 		if (rowIdMode)
       
  1182 			{
       
  1183 			TInt currentId=aRowSet.ColUint(colset->ColNo(KRowIdColName));
       
  1184 			TBool toTest=EFalse;
       
  1185 			for (TInt jj=0; jj<rowIdToTest->Count(); ++jj)
       
  1186 				{
       
  1187 				if (currentId==(*rowIdToTest)[jj])
       
  1188 					toTest=ETrue;
       
  1189 				}
       
  1190 			if (!toTest)
       
  1191 				continue;
       
  1192 			}
       
  1193 		for (TInt ii=1;ii<=columns;++ii)
       
  1194 			{
       
  1195 			if (rowIdMode && ii==colset->ColNo(KRowIdColName))	// ignore row id column
       
  1196 				continue;
       
  1197 			const TDbCol& col=(*colset)[ii];
       
  1198 			iScript.GetNextTokenFromLine(token);				// value
       
  1199 			if (token.Compare(_L(","))==0)
       
  1200 				iScript.GetNextTokenFromLine(token);			// ignore comma
       
  1201 			if (aRowSet.IsColNull(ii))
       
  1202 				{
       
  1203 				if (token.CompareF(_L("NULL"))!=0)
       
  1204 					FatalError(_L("NULL expected"));
       
  1205 				continue;
       
  1206 				}
       
  1207 			CompareValues(aRowSet,ii,col.iType,token);
       
  1208 			}
       
  1209 		}
       
  1210 	delete colset;
       
  1211 	CleanupStack::PopAndDestroy();				// rowIdToTest
       
  1212 	iScript.GetNextTokenFromLine(token);		// look for closing '}'
       
  1213 	if (token.Compare(_L("}"))!=0)
       
  1214 		FatalError(_L("missing '}'"));
       
  1215 	iScript.ConsumeStatement();
       
  1216 	}
       
  1217 
       
  1218 //
       
  1219 // compares the value from a rowset aRowset, colimn number aColNo and of type aType, with the value
       
  1220 // contained in the descriptor aToken
       
  1221 //
       
  1222 void TScriptEngine::CompareValues(RDbRowSet& aRowSet,TDbColNo ColNo,TDbColType aType,const TDesC& aToken)
       
  1223 	{
       
  1224 	TLex value=aToken;
       
  1225 	switch (aType)
       
  1226 		{
       
  1227 	case EDbColInt32:
       
  1228 		{
       
  1229 		TInt num;
       
  1230 		TEST2(value.Val(num), KErrNone);
       
  1231 		if (num!=aRowSet.ColInt(ColNo))
       
  1232 			FatalError();
       
  1233 		break;
       
  1234 		}
       
  1235 	case EDbColInt8:
       
  1236 		{
       
  1237 		TInt8 num8;
       
  1238 		TEST2(value.Val(num8), KErrNone);
       
  1239 		if (num8!=aRowSet.ColInt8(ColNo))
       
  1240 			FatalError();
       
  1241 		break;
       
  1242 		}
       
  1243 	case EDbColInt16:
       
  1244 		{
       
  1245 		TInt16 num16;
       
  1246 		TEST2(value.Val(num16), KErrNone);
       
  1247 		if (num16!=aRowSet.ColInt16(ColNo))
       
  1248 			FatalError();
       
  1249 		break;
       
  1250 		}
       
  1251 	case EDbColInt64:
       
  1252 		{
       
  1253 		TInt64 num64;
       
  1254 		TEST2(value.Val(num64), KErrNone);
       
  1255 		if (num64!=aRowSet.ColInt64(ColNo))
       
  1256 			FatalError();
       
  1257 		break;
       
  1258 		}
       
  1259 	case EDbColUint8:
       
  1260 		{
       
  1261 		TUint8 numu8;
       
  1262 		TEST2(value.Val(numu8,EDecimal), KErrNone);
       
  1263 		if (numu8!=aRowSet.ColUint8(ColNo))
       
  1264 			FatalError();
       
  1265 		break;
       
  1266 		}
       
  1267 	case EDbColUint16:
       
  1268 		{
       
  1269 		TUint16 numu16;
       
  1270 		TEST2(value.Val(numu16,EDecimal), KErrNone);
       
  1271 		if (numu16!=aRowSet.ColUint16(ColNo))
       
  1272 			FatalError();
       
  1273 		break;
       
  1274 		}
       
  1275 	case EDbColUint32:
       
  1276 		{
       
  1277 		TUint32 numu32;
       
  1278 		TEST2(value.Val(numu32,EDecimal), KErrNone);
       
  1279 		if (numu32!=aRowSet.ColUint32(ColNo))
       
  1280 			FatalError();
       
  1281 		break;
       
  1282 		}
       
  1283 	case EDbColReal32:
       
  1284 		{
       
  1285 		TReal32 numr32;
       
  1286 		TEST2(value.Val(numr32), KErrNone);
       
  1287 		if (numr32!=aRowSet.ColReal32(ColNo))
       
  1288 			FatalError();
       
  1289 		break;
       
  1290 		}
       
  1291 	case EDbColReal64:
       
  1292 		{
       
  1293 		TReal64 numr64;
       
  1294 		TEST2(value.Val(numr64), KErrNone);
       
  1295 		if (numr64!=aRowSet.ColReal64(ColNo))
       
  1296 			FatalError();
       
  1297 		break;
       
  1298 		}
       
  1299 	case EDbColText8:
       
  1300 	case EDbColText16:
       
  1301 		{
       
  1302 		TPtrC text=aToken.Mid(1,aToken.Length()-2);			// skip quotes
       
  1303 		if (text.CompareF(aRowSet.ColDes(ColNo))!=0)
       
  1304 			FatalError();
       
  1305 		break;
       
  1306 		}
       
  1307 	case EDbColDateTime:
       
  1308 		{
       
  1309 		TScriptLine time=aToken.Mid(1,aToken.Length()-2);	// skip hashes
       
  1310 		TTime t1;
       
  1311 		t1.Parse(time);
       
  1312 		TTime t2(aRowSet.ColTime(ColNo).DateTime());
       
  1313 		if (t1!=t2)
       
  1314 			FatalError();
       
  1315 		break;
       
  1316 		}
       
  1317 	default:
       
  1318 		break;
       
  1319 		}
       
  1320 	}
       
  1321 
       
  1322 void TScriptEngine::PrintL(RDbRowSet& aRowSet)
       
  1323 	{
       
  1324 	iScript.WriteLine(TPtrC());
       
  1325 	TInt columns=aRowSet.ColCount();
       
  1326 	CDbColSet* colset=aRowSet.ColSetL();
       
  1327 	TScriptLine line;
       
  1328 	for (TInt i=1;i<=columns;++i)
       
  1329 		{
       
  1330 		const TDbCol& col=(*colset)[i];
       
  1331 		line.AppendFormat(_L("%S\t"),&col.iName);
       
  1332 		}
       
  1333 	iScript.WriteLine(line);
       
  1334 	aRowSet.BeginningL();
       
  1335 	while (aRowSet.NextL())
       
  1336 		{
       
  1337 		line=TPtrC();
       
  1338 		for (TInt ii=1;ii<=columns;++ii)
       
  1339 			{
       
  1340 			const TDbCol& col=(*colset)[ii];
       
  1341 			aRowSet.GetL();
       
  1342 			if (aRowSet.IsColNull(ii))
       
  1343 				{
       
  1344 				line.AppendFormat(_L("NULL\t"));
       
  1345 				continue;
       
  1346 				}
       
  1347 			switch (col.iType)
       
  1348 				{
       
  1349 			case EDbColInt32:
       
  1350 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt(ii));
       
  1351 				break;
       
  1352 			case EDbColInt8:
       
  1353 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt8(ii));
       
  1354 				break;
       
  1355 			case EDbColInt16:
       
  1356 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt16(ii));
       
  1357 				break;
       
  1358 			case EDbColInt64:
       
  1359 				line.AppendFormat(_L("%ld\t"),aRowSet.ColInt64(ii));
       
  1360 				break;
       
  1361 			case EDbColUint8:
       
  1362 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint8(ii));
       
  1363 				break;
       
  1364 			case EDbColUint16:
       
  1365 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint16(ii));
       
  1366 				break;
       
  1367 			case EDbColUint32:
       
  1368 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint(ii));
       
  1369 				break;
       
  1370 			case EDbColReal32:
       
  1371 				line.AppendFormat(_L("%f\t"),aRowSet.ColReal32(ii));
       
  1372 				break;
       
  1373 			case EDbColReal64:
       
  1374 				line.AppendFormat(_L("%f\t"),aRowSet.ColReal64(ii));
       
  1375 				break;
       
  1376 			case EDbColText:
       
  1377 				line.Append(aRowSet.ColDes(ii));
       
  1378 				line.Append('\t');
       
  1379 				break;
       
  1380 			case EDbColDateTime:
       
  1381 				{
       
  1382 				TDateTime time(aRowSet.ColTime(ii).DateTime());
       
  1383 				line.AppendFormat(_L("%d:%d:%d %d/%d/%d"),time.Hour(),time.Minute(),time.Second(),time.Day(),time.Month(),time.Year());
       
  1384 				}
       
  1385 				break;
       
  1386 			case EDbColLongText:
       
  1387 				{
       
  1388 				RDbColReadStream blob;
       
  1389 				blob.OpenLC(aRowSet,ii);
       
  1390 				TScriptLine text;
       
  1391 				blob.ReadL(text,aRowSet.ColLength(ii));
       
  1392 				CleanupStack::PopAndDestroy();
       
  1393 				line.AppendFormat(_L("%S\t"),&text);
       
  1394 				}
       
  1395 			default:
       
  1396 				break;
       
  1397 				}
       
  1398 			}
       
  1399 		iScript.WriteLine(line);
       
  1400 		}
       
  1401 	iScript.WriteLine(TPtrC());
       
  1402 	delete colset;
       
  1403 	}
       
  1404 
       
  1405 
       
  1406 //
       
  1407 // Create the database
       
  1408 //
       
  1409 LOCAL_C void CreateDatabase()
       
  1410 	{
       
  1411 	TEST2(TheDatabase.Replace(TheFs,KTestDatabase), KErrNone);
       
  1412 	}
       
  1413 
       
  1414 //
       
  1415 // Close the database
       
  1416 //
       
  1417 LOCAL_C void CloseDatabase()
       
  1418 	{
       
  1419 	TheDatabase.Close();
       
  1420 	}
       
  1421 
       
  1422 //
       
  1423 // Prepare the test directory.
       
  1424 //
       
  1425 LOCAL_C void SetupTestDirectory()
       
  1426     {
       
  1427 	TInt err=TheFs.Connect();
       
  1428 	TEST2(err, KErrNone);
       
  1429 //
       
  1430 	err=TheFs.MkDir(KTestDatabase);
       
  1431 	TEST(err==KErrNone || err==KErrAlreadyExists);
       
  1432 	}
       
  1433 
       
  1434 //
       
  1435 // Initialise the cleanup stack.
       
  1436 //
       
  1437 LOCAL_C void SetupCleanup()
       
  1438     {
       
  1439 	TheTrapCleanup=CTrapCleanup::New();
       
  1440 	TEST(TheTrapCleanup!=NULL);
       
  1441 	TRAPD(err,\
       
  1442 		{\
       
  1443 		for (TInt i=KTestCleanupStack;i>0;i--)\
       
  1444 			CleanupStack::PushL((TAny*)0);\
       
  1445 		CleanupStack::Pop(KTestCleanupStack);\
       
  1446 		});
       
  1447 	TEST2(err, KErrNone);
       
  1448 	}
       
  1449 
       
  1450 /**
       
  1451 @SYMTestCaseID          SYSLIB-DBMS-CT-0632
       
  1452 @SYMTestCaseDesc        Executes the script files
       
  1453 @SYMTestPriority        Medium
       
  1454 @SYMTestActions         Start the script engine
       
  1455 @SYMTestExpectedResults Test must not fail
       
  1456 @SYMREQ                 REQ0000
       
  1457 */
       
  1458 LOCAL_C void RunScriptL()
       
  1459 	{
       
  1460 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0632 Running script "));
       
  1461 	CreateDatabase();
       
  1462 	TScriptEngine script;
       
  1463 	script.RunL();
       
  1464 	CloseDatabase();
       
  1465 	TheView.Close();
       
  1466 	}
       
  1467 
       
  1468 //
       
  1469 // entry point
       
  1470 //
       
  1471 GLDEF_C TInt E32Main()
       
  1472     {
       
  1473 	TheTest.Title();
       
  1474 	SetupTestDirectory();
       
  1475 	SetupCleanup();
       
  1476 	__UHEAP_MARK;
       
  1477 //
       
  1478 	TRAPD(err,RunScriptL());
       
  1479 	TEST2(err, KErrNone);
       
  1480 
       
  1481 	//deletion of data files must be done before call to end - DEF047652
       
  1482 	::DeleteDataFile(KTestDatabase);
       
  1483 	::DeleteDataFile(KOutputFile);//Comment this line if you want to keep "t_script.log" file.
       
  1484 	TheTest.End();
       
  1485 //
       
  1486 	__UHEAP_MARKEND;
       
  1487 	delete TheTrapCleanup;
       
  1488 
       
  1489 	TheFs.Close();
       
  1490 	TheTest.Close();
       
  1491 
       
  1492 	return 0;
       
  1493     }