sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include <d32dbms.h>
sl@0: #include <f32file.h>
sl@0: #include <e32test.h>
sl@0: #include <e32math.h>
sl@0: 
sl@0: #include "crccheck.h"
sl@0: 
sl@0: #undef __UHEAP_MARK
sl@0: #define __UHEAP_MARK
sl@0: #undef __UHEAP_MARKEND
sl@0: #define __UHEAP_MARKEND
sl@0: 
sl@0: LOCAL_D TDBMS_CRCChecks TheCrcChecker;
sl@0: 
sl@0: #ifndef __linux__ //No CRC test on LINUX
sl@0: #ifdef __TOOLS2__
sl@0: const TPtrC	KCrcRecord=_L("\\epoc32\\winscw\\c\\dbms-tst\\T_DBMSSCRIPT.CRC");
sl@0: #else
sl@0: const TPtrC	KCrcRecord=_L("C:\\dbms-tst\\T_DBMSSCRIPT.CRC");
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: LOCAL_D RTest test(_L("T_DBMSSCRIPT"));
sl@0: LOCAL_D CTrapCleanup* TheTrapCleanup;
sl@0: LOCAL_D RDbNamedDatabase TheDatabase;
sl@0: LOCAL_D RFs TheFs;
sl@0: LOCAL_D RDbView TheView;
sl@0: //
sl@0: 
sl@0: #ifdef __TOOLS2__
sl@0: const TPtrC KTestDatabase=_L(".\\dbms-tst\\t_script.db");
sl@0: #else
sl@0: const TPtrC KTestDatabase=_L("C:\\dbms-tst\\t_script.db");
sl@0: #endif
sl@0: 
sl@0: const TPtrC KRomScriptFile=_L("z:\\test\\t_script.txt");
sl@0: 
sl@0: #ifndef __TOOLS2__
sl@0: const TPtrC KScriptFile=_L("c:\\dbms-tst\\t_script.txt");
sl@0: #else
sl@0: const TPtrC KScriptFile=_L(".\\dbms-tst\\t_script.txt");
sl@0: #endif
sl@0: 
sl@0: #ifndef __TOOLS2__
sl@0: const TPtrC KOutputFile=_L("c:\\dbms-tst\\t_script.log");
sl@0: #else
sl@0: const TPtrC KOutputFile=_L(".\\dbms-tst\\t_script.log");
sl@0: #endif
sl@0: 
sl@0: const TInt KTestCleanupStack=0x20;
sl@0: const TPtrC KDDLKeywords[]={_L("CREATE"),_L("DROP"),_L("ALTER")};
sl@0: const TPtrC KDMLKeywords[]={_L("INSERT"),_L("DELETE"),_L("UPDATE")};
sl@0: const TPtrC KQueryKeywords[]={_L("SELECT")};
sl@0: const TPtrC KScriptKeywords[]={_L("PRINT"),_L("ROWS"),_L("COMPARE"),_L("ERROR"),_L("!"),
sl@0: 							   _L("POPULATE"),_L("RESULTS"),_L("BUILD"),_L("QUERY"),
sl@0: 							   _L("NORMAL"),_L("FOLDED"),_L("COLLATED"),_L("START"),_L("STOP"),
sl@0: 							   _L("LOAD"),_L("ECHO"),_L("WINDOW"),_L("ACCESS")};
sl@0: const TPtrC KRowIdColName=_L("Rw");
sl@0: enum TKeyword {EPrint,ERows,ECompare,EError,EComment,EPopulate,EResults,EBuild,EQuery,ENormal,
sl@0:                EFolded,ECollated,EStart,EStop,ELoad,EEcho,EWindow,EAccess,ENumKeywords,EUnknown};
sl@0: //
sl@0: typedef TBuf<256> TScriptLine;
sl@0: typedef TBuf<256> TScriptToken;
sl@0: //
sl@0: #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
sl@0: 
sl@0: class TScript;
sl@0: class TTimer
sl@0: 	{
sl@0: public:
sl@0: 	inline TTimer(TScript& aScript);
sl@0: 	void Start(const TDesC& aDes);
sl@0: 	void Stop(const TDesC& aDes);
sl@0: private:
sl@0: 	TUint iTicks;
sl@0: 	TScript& iScript;
sl@0: 	};
sl@0: 
sl@0: class TResults
sl@0: 	{
sl@0: public:
sl@0: 	inline TResults(); 
sl@0: public:
sl@0: 	RDbView& iView;
sl@0: 	TInt iError;
sl@0: 	TInt iRows;
sl@0: 	TInt iLineNo;
sl@0: 	TScriptLine iLine;
sl@0: 	};
sl@0: 
sl@0: class TSqlStatement
sl@0: 	{
sl@0: private:
sl@0: 	enum TSqlType {EDML,EDDL,EQuery,EUnknown};
sl@0: public:
sl@0: 	inline TSqlStatement(const TDesC& aSql,TResults& aResults); 
sl@0: 	TInt Execute(TDbTextComparison aTextComparison=EDbCompareNormal,
sl@0: 		RDbRowSet::TAccess aAccess=RDbRowSet::EReadOnly,TBool aWindow=EFalse) const;
sl@0: private:
sl@0: 	void ExecuteSql(TDbTextComparison aTextComparison) const;
sl@0: 	void ExecuteQuery(RDbRowSet::TAccess aAccess,TBool aWindow) const;
sl@0: 	TSqlType SqlType() const;
sl@0: private:
sl@0: 	const TDesC& iSql;
sl@0: 	TResults& iResults;
sl@0: 	};
sl@0: 
sl@0: class TScript
sl@0: 	{
sl@0: public:
sl@0: 	TScript();
sl@0: #ifdef __TOOLS2__
sl@0: 	~TScript() { iFile.Close(); };
sl@0: #endif
sl@0: 	TInt ReadNextStatement();
sl@0: 	void GetNextTokenFromStatement(TDes& aToken);
sl@0: 	void GetNextTokenFromLine(TDes& aToken);
sl@0: 	TPtrC Statement();
sl@0: 	TInt IntValue();
sl@0: 	void WriteLine(const TDesC& aLine);
sl@0: 	void WriteError(const TDesC& aLine);
sl@0: 	void WriteSqlError(const TResults& aResults,const TDesC& aLine); 
sl@0: 	void WriteComment(const TDesC& aLine);
sl@0: 	TKeyword Keyword(const TDesC& aKeyword) const;
sl@0: 	void ConsumeLine();
sl@0: 	void ConsumeStatement();
sl@0: 	inline TInt LineNo() const;
sl@0: private:
sl@0: 	TInt ReadNextLine();
sl@0: 	TInt AppendNextLine();
sl@0: 	TBool IsStatement();
sl@0: private:
sl@0: 	TFileText iInput;
sl@0: 	TFileText iOutput;
sl@0: 	TScriptLine iBuf;
sl@0: 	TLex iStatement;
sl@0: 	TLex iLine;
sl@0: 	TInt iLineNo;
sl@0: #ifdef __TOOLS2__
sl@0: 	RFile iFile;
sl@0: #endif
sl@0: 	};
sl@0: 
sl@0: class TScriptEngine
sl@0: 	{
sl@0: public:
sl@0: 	inline TScriptEngine();
sl@0: 	void RunL();
sl@0: private:
sl@0: 	void ExecuteL();
sl@0: 	TInt ExecuteScriptL();
sl@0: 	TInt ExecuteSql(const TDesC& aSql);
sl@0: 	TInt ExecuteSql();
sl@0: 	// keyword operations
sl@0: 	void DoPrintL();
sl@0: 	void DoComment();
sl@0: 	void DoError();
sl@0: 	void DoEcho();
sl@0: 	void DoWindow();
sl@0: 	void DoAccess();
sl@0: 	void DoRows();
sl@0: 	void DoCompareL();
sl@0: 	void DoPopulate();
sl@0: 	void DoResultsL();
sl@0: 	void DoBuildTable();
sl@0: 	void DoQuery();
sl@0: 	void DoTextComparison(TKeyword aKeyword);
sl@0: 	void DoStartTimer();
sl@0: 	void DoStopTimer();
sl@0: 	void DoLoadDb();
sl@0: 	//
sl@0: 	void PrintL(RDbRowSet& aRowSet);
sl@0: 	void CompareL(RDbRowSet& aRowSet);
sl@0: 	void CompareValues(RDbRowSet& aRowSet,TDbColNo ColNo,TDbColType aType,const TDesC& aToken);
sl@0: 	void FatalError(const TDesC& aLine);
sl@0: 	void FatalError();
sl@0: 	void FatalSqlError(const TDesC& aLine);
sl@0: 	void TestForNoError(); 
sl@0: private:
sl@0: 	TScript iScript;
sl@0: 	TResults iResults;
sl@0: 	TDbTextComparison iTextComparison;
sl@0: 	TTimer iTimer;
sl@0: 	TBool iEcho;
sl@0: 	TBool iWindow;
sl@0: 	RDbRowSet::TAccess iAccess;
sl@0: 	
sl@0: 	};
sl@0: 
sl@0: //
sl@0: // class TTimer
sl@0: //
sl@0: 
sl@0: inline TTimer::TTimer(TScript& aScript)
sl@0: 	: iScript(aScript)
sl@0: 	{}
sl@0: 
sl@0: void TTimer::Start(const TDesC& aDes)
sl@0: 	{
sl@0: 	TScriptLine line;
sl@0: 	line.Format(_L("%S: "),&aDes);
sl@0: 	iScript.WriteLine(line);
sl@0: 	iTicks=User::TickCount();
sl@0: 	}
sl@0: 
sl@0: void TTimer::Stop(const TDesC& aDes)
sl@0: 	{
sl@0: 	TScriptLine line;
sl@0: 	line.Format(_L("%S: "),&aDes);
sl@0: #ifdef __EPOC32__
sl@0: #define TICK_TIME 15625
sl@0: #else
sl@0: #define	TICK_TIME 100000
sl@0: #endif
sl@0: 	TInt microSec=(User::TickCount()-iTicks)*TICK_TIME;
sl@0: 	TUint sec=microSec/1000000;
sl@0: 	TUint centi=(microSec/10000)-sec*100;
sl@0: 	line.AppendFormat(_L("%u.%02us\n"),sec,centi);
sl@0: 	iScript.WriteLine(line);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // class TResults
sl@0: //
sl@0: 
sl@0: inline TResults::TResults()
sl@0: 	: iView(TheView),iError(KErrNone)
sl@0: 	{}
sl@0: 
sl@0: 
sl@0: //
sl@0: // class TSqlStatement
sl@0: //
sl@0: 
sl@0: inline TSqlStatement::TSqlStatement(const TDesC& aSql,TResults& aResults)
sl@0: 	: iSql(aSql),iResults(aResults)
sl@0: 	{}
sl@0: 
sl@0: void TSqlStatement::ExecuteSql(TDbTextComparison aTextComparison) const
sl@0: //
sl@0: // executes DML or DDL
sl@0: //
sl@0: 	{
sl@0: 	TInt r=TheDatabase.Execute(iSql,aTextComparison);
sl@0: 	if (r<0)
sl@0: 		iResults.iError=r;
sl@0: 	else
sl@0: 		{
sl@0: 		iResults.iError=KErrNone;
sl@0: 		iResults.iRows=r;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void TSqlStatement::ExecuteQuery(RDbRowSet::TAccess aAccess,TBool aWindow) const
sl@0: 	{
sl@0: 	iResults.iView.Close();			// discard any previous queries
sl@0: 	TInt& err=iResults.iError;
sl@0: 	if (aWindow)
sl@0: 		err=iResults.iView.Prepare(TheDatabase,iSql,KDbUnlimitedWindow,aAccess);
sl@0: 	else
sl@0: 		err=iResults.iView.Prepare(TheDatabase,iSql,aAccess);
sl@0: 	if (err==KErrNone)
sl@0: 		err=iResults.iView.EvaluateAll();
sl@0: 	}
sl@0: 
sl@0: TSqlStatement::TSqlType TSqlStatement::SqlType() const
sl@0: //
sl@0: // determines the type of sql statement by matching keywords
sl@0: //
sl@0: 	{
sl@0: 	for (TUint i=0;i<ARRAY_SIZE(KDDLKeywords);++i)
sl@0: 		{
sl@0: 		if (iSql.FindF(KDDLKeywords[i])==0)		
sl@0: 			return EDDL;
sl@0: 		}
sl@0: 	for (TUint ii=0;ii<ARRAY_SIZE(KDMLKeywords);++ii)
sl@0: 		{
sl@0: 		if (iSql.FindF(KDMLKeywords[ii])==0)
sl@0: 			return EDML;
sl@0: 		}
sl@0: 	for (TUint j=0;j<ARRAY_SIZE(KQueryKeywords);++j)
sl@0: 		{
sl@0: 		if (iSql.FindF(KQueryKeywords[j])==0)
sl@0: 			return EQuery;
sl@0: 		}
sl@0: 	return EUnknown;
sl@0: 	}
sl@0: 
sl@0: TInt TSqlStatement::Execute(TDbTextComparison aTextComparison,RDbRowSet::TAccess aAccess,TBool aWindow) const
sl@0: //
sl@0: // executes the sql statement
sl@0: //
sl@0: 	{
sl@0: 	TInt r=KErrNone;
sl@0: 	switch (SqlType())
sl@0: 		{
sl@0: 	case EDDL:
sl@0: 	case EDML:
sl@0: 		ExecuteSql(aTextComparison);
sl@0: 		break;
sl@0: 	case EQuery:
sl@0: 		ExecuteQuery(aAccess,aWindow);
sl@0: 		break;
sl@0: 	case EUnknown:
sl@0: 	default:
sl@0: 		r=KErrNotFound;
sl@0: 		break;
sl@0: 		}
sl@0: 	return r;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // class TScript
sl@0: //
sl@0: 
sl@0: TScript::TScript()
sl@0: 	: iLineNo(0)
sl@0: 	{
sl@0: 	RFile file;
sl@0: 	TInt r=file.Open(TheFs,KScriptFile,EFileRead);
sl@0: #ifndef __TOOLS2__
sl@0: 	if (r!=KErrNone)
sl@0: 		r=file.Open(TheFs,KRomScriptFile,EFileRead);
sl@0: #endif
sl@0: 	test(r==KErrNone);
sl@0: 	iInput.Set(file);
sl@0: 
sl@0: #ifdef __TOOLS2__
sl@0: 	RFile file2;
sl@0: 	test(file2.Replace(TheFs,KOutputFile,EFileWrite)==KErrNone);
sl@0: 	iFile = file2;
sl@0: 	iOutput.Set(file2);
sl@0: #else
sl@0: 	test(file.Replace(TheFs,KOutputFile,EFileWrite)==KErrNone);
sl@0: 	iOutput.Set(file);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: inline TInt TScript::LineNo() const
sl@0: 	{return iLineNo;}
sl@0: 
sl@0: TBool TScript::IsStatement()
sl@0: //
sl@0: //	checks for keywords which possibly conform to the usual statement format (ie end in ';')
sl@0: //
sl@0: 	{
sl@0: 	if (iLine.Remainder().Length()==0)	// null statement
sl@0: 		return ETrue;
sl@0: 	TPtrC line=iLine.Remainder();
sl@0: 	TKeyword keyword=Keyword(line);
sl@0: 	switch (keyword)
sl@0: 		{
sl@0: 	case EPrint: 
sl@0: 	case ERows:
sl@0: 	case EBuild:
sl@0: 	case EError:
sl@0: 	case EQuery:
sl@0: 	case ENormal:
sl@0: 	case EFolded:
sl@0: 	case ECollated:
sl@0: 	case EStart:
sl@0: 	case EStop:
sl@0: 	case ELoad:
sl@0: 	case EEcho:
sl@0: 	case EWindow:
sl@0: 	case EAccess:
sl@0: 	case EUnknown:						// could be sql
sl@0: 		return ETrue;
sl@0: 	case EComment:
sl@0: 	case EPopulate:
sl@0: 	case ECompare:
sl@0: 	case EResults:
sl@0: 		iStatement=line;				// not a statement, so make it the whole line
sl@0: 		return EFalse;
sl@0: 	default:
sl@0: 		test(0);
sl@0: 		return EFalse;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: TInt TScript::ReadNextStatement()
sl@0: //
sl@0: // reads the next non-blank statement or line
sl@0: //
sl@0: 	{
sl@0: 	TInt r=ReadNextLine();
sl@0: 	if (r!=KErrNone || !IsStatement())
sl@0: 		return r;
sl@0: 	TChar c=0;
sl@0: 	while (c!=';')
sl@0: 		{
sl@0: 		c=iLine.Get();
sl@0: 		if (!c)							// nothing left to read
sl@0: 			{
sl@0: 			r=AppendNextLine();
sl@0: 			if (r!=KErrNone)
sl@0: 				return r;
sl@0: 			}
sl@0: 		}
sl@0: 	iLine.UnGet();						// the semi-colon
sl@0: 	iStatement=iLine.MarkedToken();
sl@0: 	iLine.Get();						// the semi-colon
sl@0: 	iLine.SkipSpaceAndMark();
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: TPtrC TScript::Statement()
sl@0: 	{
sl@0: 	return iStatement.Remainder();
sl@0: 	}
sl@0: 
sl@0: void TScript::ConsumeLine()
sl@0: 	{
sl@0: 	iLine=TPtrC();
sl@0: 	iStatement=TPtrC();
sl@0: 	}
sl@0: 
sl@0: void TScript::ConsumeStatement()
sl@0: 	{
sl@0: 	iLine=iLine.Remainder();
sl@0: 	iStatement=TPtrC();
sl@0: 	}
sl@0: 
sl@0: TInt TScript::ReadNextLine()
sl@0: //
sl@0: // reads the next non-blank line into iLine
sl@0: //
sl@0: 	{
sl@0: 	while (iLine.Remainder().Length()==0)
sl@0: 		{
sl@0: 		TInt r=iInput.Read(iBuf);
sl@0: 		if (r!=KErrNone)
sl@0: 			return r;
sl@0: 		if (iBuf.Length()>0 && iBuf[0]==0xfeff)	// unicode stream marker
sl@0: 			iBuf.Delete(0,1);
sl@0: 		iLineNo++;
sl@0: 		iLine=iBuf;
sl@0: 		iLine.SkipSpaceAndMark();
sl@0: 		} 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: TInt TScript::AppendNextLine()
sl@0: //
sl@0: // adds next line from file to iLine
sl@0: //
sl@0: 	{
sl@0: 	TScriptLine line;
sl@0: 	do {
sl@0: 		TInt r=iInput.Read(line);
sl@0: 		if (r!=KErrNone)
sl@0: 			return r;
sl@0: 		iLineNo++;
sl@0: 		} while (line.Length()==0);
sl@0: 	iBuf=iLine.MarkedToken();
sl@0: 	iBuf.Append(line);
sl@0: 	iLine=iBuf;
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: void TScript::WriteError(const TDesC& aLine)
sl@0: 	{
sl@0: 	TScriptLine line;
sl@0: 	line.Format(_L("Error at line %d: %S\n"),iLineNo,&aLine);
sl@0: 	WriteLine(line);
sl@0: 	test.Printf(line);
sl@0: 	}
sl@0: 
sl@0: void TScript::WriteSqlError(const TResults& aResults,const TDesC& aLine)
sl@0: 	{
sl@0: 	TScriptLine line;
sl@0: 	line.Format(_L("Error at line %d: %S :-\n"),aResults.iLineNo,&aLine);
sl@0: 	WriteLine(line);
sl@0: 	test.Printf(line);
sl@0: 	line.Format(_L("\t%S\n"),&aResults.iLine);
sl@0: 	WriteLine(line);
sl@0: 	test.Printf(line);
sl@0: 	}
sl@0: 
sl@0: void TScript::WriteLine(const TDesC& aLine)
sl@0: 	{
sl@0: 	TScriptLine l=aLine;
sl@0: 	l.Append('\r');
sl@0: 	iOutput.Write(l);
sl@0: 	}
sl@0: 
sl@0: void TScript::WriteComment(const TDesC& aLine)
sl@0: 	{
sl@0: 	TScriptLine line;	
sl@0: 	line.Format(_L("\n%S"),&aLine);
sl@0: 	WriteLine(line);
sl@0: 	}
sl@0: 
sl@0: TInt TScript::IntValue()
sl@0: //
sl@0: // returns the integer n from the ' = n ' which must follow in the statement
sl@0: //
sl@0: 	{
sl@0: 	TScriptToken keyword;
sl@0: 	GetNextTokenFromStatement(keyword);
sl@0: 	if (keyword.Compare(_L("="))!=0)
sl@0: 		WriteError(_L("expected '=' missing"));
sl@0: 	iStatement.SkipSpaceAndMark();
sl@0: 	TInt num=0;
sl@0: 	TInt err=iStatement.Val(num);
sl@0: 	if (err!=KErrNone)
sl@0: 		WriteError(_L("expected number missing"));
sl@0: 	return num;
sl@0: 	}
sl@0: 
sl@0: TKeyword TScript::Keyword(const TDesC& aKeyword) const
sl@0: 	{
sl@0: 	for (TInt ii=0; ii<ENumKeywords; ++ii)
sl@0: 		{
sl@0: 		if (aKeyword.FindF(KScriptKeywords[ii])==0)
sl@0: 			return TKeyword(ii);
sl@0: 		}
sl@0: 	return EUnknown;
sl@0: 	}
sl@0: 
sl@0: void TScript::GetNextTokenFromStatement(TDes& aToken)
sl@0: //
sl@0: // gets the next token from iStatement
sl@0: //
sl@0: 	{
sl@0: 	iStatement.SkipSpaceAndMark();
sl@0: 	TUint c;
sl@0: 	do
sl@0: 		{
sl@0: 		c=iStatement.Get();
sl@0: 		if (c=='=' || c=='!')
sl@0: 			break;
sl@0: 		} while (iStatement.Peek().IsAlphaDigit());
sl@0: 	aToken=iStatement.MarkedToken();
sl@0: 	iStatement.SkipSpaceAndMark();
sl@0: 	}
sl@0: 
sl@0: void TScript::GetNextTokenFromLine(TDes& aToken)
sl@0: //
sl@0: // gets the next token from iLine
sl@0: //
sl@0: 	{
sl@0: 	iLine.SkipSpaceAndMark();
sl@0: 	TUint c=0;
sl@0: 	TChar cc=c;
sl@0: 	TBool literal=EFalse;
sl@0: 	do
sl@0: 		{
sl@0: 		c=iLine.Get();
sl@0: 		if (!c)
sl@0: 			{
sl@0: 			AppendNextLine();
sl@0: 			iLine.SkipSpaceAndMark();
sl@0: 			c=iLine.Get();
sl@0: 			}
sl@0: 		if (c=='\'' || c=='#')
sl@0: 			literal=!literal;
sl@0: 		if ((c==',' || c=='(' || c==')' || c=='{' || c=='}' || c=='!' ) && !literal)
sl@0: 			break;
sl@0: 		cc=iLine.Peek();
sl@0: 		} while (cc.IsAlphaDigit() || literal || TUint(cc)=='.' || TUint(cc)=='+' || TUint(cc)=='-');
sl@0: 	aToken=iLine.MarkedToken();
sl@0: 	if (TUint(cc)==';')					// ignore semi-colons - they're optional
sl@0: 		iLine.Get();
sl@0: 	iLine.SkipSpaceAndMark();
sl@0: 	if (c=='!')
sl@0: 		{
sl@0: 		iStatement=iLine.Remainder();
sl@0: 		TPtrC comment=iStatement.Remainder();
sl@0: 		WriteComment(comment); 
sl@0: 		iLine=TPtrC();
sl@0: 		GetNextTokenFromLine(aToken);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // class TScriptEngine
sl@0: //
sl@0: 
sl@0: TScriptEngine::TScriptEngine()
sl@0: 	: iTextComparison(EDbCompareNormal),iTimer(iScript),iEcho(EFalse),iWindow(EFalse),iAccess(RDbRowSet::EReadOnly)
sl@0: 	{} 
sl@0: 
sl@0: 
sl@0: void TScriptEngine::RunL() 
sl@0: //
sl@0: // runs the script file
sl@0: //
sl@0: 	{
sl@0: 	while (iScript.ReadNextStatement()!=KErrEof)
sl@0: 		ExecuteL();
sl@0: 	TestForNoError(); 
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::TestForNoError() 
sl@0: 	{
sl@0: 	if (iResults.iError!=KErrNone)
sl@0: 		{
sl@0: 		TScriptLine line;
sl@0: 		line.Format(_L("unexpected error %d"),iResults.iError);
sl@0: 		FatalSqlError(line);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::ExecuteL()
sl@0: 	{
sl@0: 	if (ExecuteScriptL()!=KErrNone && ExecuteSql()!=KErrNone)
sl@0: 		FatalSqlError(_L("syntax error"));
sl@0: 	}
sl@0: 
sl@0: TInt TScriptEngine::ExecuteScriptL()
sl@0: 	{
sl@0: 	TKeyword keyword=iScript.Keyword(iScript.Statement());
sl@0: 	if (keyword!=EError)
sl@0: 		TestForNoError(); 
sl@0: 	switch (keyword)
sl@0: 		{
sl@0: 	case EPrint:	
sl@0: 		DoPrintL();
sl@0: 		break;
sl@0: 	case ERows:
sl@0: 		DoRows();
sl@0: 		break;
sl@0: 	case ELoad:
sl@0: 		DoLoadDb();
sl@0: 		break;
sl@0: 	case EEcho:
sl@0: 		DoEcho();
sl@0: 		break;
sl@0: 	case EWindow:
sl@0: 		DoWindow();
sl@0: 		break;
sl@0: 	case EAccess:
sl@0: 		DoAccess();
sl@0: 		break;
sl@0: 	case ECompare:
sl@0: 		DoCompareL();
sl@0: 		break;
sl@0: 	case EError:
sl@0: 		DoError();
sl@0: 		break;
sl@0: 	case EPopulate:
sl@0: 		DoPopulate();
sl@0: 		break;
sl@0: 	case EComment:
sl@0: 		DoComment();
sl@0: 		break;
sl@0: 	case EResults:
sl@0: 		DoResultsL();
sl@0: 		break;
sl@0: 	case EBuild:
sl@0: 		DoBuildTable();
sl@0: 		break;
sl@0: 	case EQuery:
sl@0: 		DoQuery();
sl@0: 		break;
sl@0: 	case ENormal:
sl@0: 	case EFolded:
sl@0: 	case ECollated:
sl@0: 		DoTextComparison(keyword);
sl@0: 		break;
sl@0: 	case EStart:
sl@0: 		DoStartTimer();
sl@0: 		break;
sl@0: 	case EStop:
sl@0: 		DoStopTimer();
sl@0: 		break;
sl@0: 	case EUnknown:
sl@0: 	default:
sl@0: 		return KErrNotFound;
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: TInt TScriptEngine::ExecuteSql()
sl@0: 	{
sl@0: 	return ExecuteSql(iScript.Statement());
sl@0: 	}
sl@0: 
sl@0: TInt TScriptEngine::ExecuteSql(const TDesC& aSql)
sl@0: 	{
sl@0: 	if (iEcho)
sl@0: 		{
sl@0: 		TScriptLine line(_L("\nSQL:\t"));
sl@0: 		line.Append(aSql);
sl@0: 		iScript.WriteLine(line);
sl@0: 		}
sl@0: 	iResults.iLineNo=iScript.LineNo();
sl@0: 	iResults.iLine=aSql;
sl@0: 	TSqlStatement statement(aSql,iResults);
sl@0: 	return statement.Execute(iTextComparison,iAccess,iWindow);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoStartTimer()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("START"))==0);
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("TIMER"))==0);
sl@0: 	//
sl@0: 	iTimer.Start(_L("Timer started"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoStopTimer()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("STOP"))==0);
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("TIMER"))==0);
sl@0: 	//
sl@0: 	iTimer.Stop(_L("Timer stopped"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoTextComparison(TKeyword aKeyword)
sl@0: 	{
sl@0: 	TPtrC line;
sl@0: 	switch (aKeyword)
sl@0: 		{
sl@0: 	case ENormal:
sl@0: 		iTextComparison=EDbCompareNormal;
sl@0: 		line.Set(_L("[Normal text comparison]"));
sl@0: 		break;
sl@0: 	case EFolded:
sl@0: 		iTextComparison=EDbCompareFolded;
sl@0: 		line.Set(_L("[Folded text comparison]"));
sl@0: 		break;
sl@0: 	case ECollated:
sl@0: 		iTextComparison=EDbCompareCollated;
sl@0: 		line.Set(_L("[Collated text comparison]"));
sl@0: 		break;
sl@0: 	default:
sl@0: 		test(0);
sl@0: 		}
sl@0: 	iScript.WriteLine(line);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoComment()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("!"))==0);
sl@0: 	//
sl@0: 	TPtrC comment=iScript.Statement();
sl@0: 	iScript.WriteComment(comment);
sl@0: 	iScript.ConsumeLine();
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoError()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("ERROR"))==0);
sl@0: 	//
sl@0: 	TScriptLine line;
sl@0: 	if (iScript.Statement().Length()==0)
sl@0: 		{
sl@0: 		if (iResults.iError>=0)
sl@0: 			FatalSqlError(_L("no error when one was expected"));
sl@0: 		line=_L("\t\tERROR OK");
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TInt err=iScript.IntValue();
sl@0: 		if (iResults.iError!=err)
sl@0: 			{
sl@0: 			line.Format(_L("expected error %d, actual error %d"),err,iResults.iError);
sl@0: 			FatalSqlError(line);
sl@0: 			}
sl@0: 		line.Format(_L("\t\tERROR=%D OK"),err);
sl@0: 		}
sl@0: 	iResults.iError=0;
sl@0: 	iScript.WriteLine(line);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoRows()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("ROWS"))==0);
sl@0: 	//
sl@0: 	TScriptLine line;
sl@0: 	TInt rows=iScript.IntValue();
sl@0: 	if (iResults.iRows!=rows)
sl@0: 		{
sl@0: 		line.Format(_L("expected rows %d, actual rows %d"),rows,iResults.iRows);
sl@0: 		FatalSqlError(line);
sl@0: 		}
sl@0: 	line.Format(_L("\t\tROWS=%D OK"),rows);
sl@0: 	iScript.WriteLine(line);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoLoadDb()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken token;
sl@0: 	iScript.GetNextTokenFromStatement(token);
sl@0: 	test(token.CompareF(_L("LOAD"))==0);
sl@0: 	//
sl@0: 	TFileName database(iScript.Statement());
sl@0: 	TheDatabase.Close();
sl@0: 
sl@0: 	TInt err = TheCrcChecker.GenerateCrcL(KTestDatabase);
sl@0: 	test(err==KErrNone);
sl@0: 
sl@0: 	TScriptLine line;
sl@0: 	line.Format(_L("Opening database: %S"),&database);
sl@0: 	iScript.WriteLine(line);
sl@0: 	test(TheDatabase.Open(TheFs,database)==KErrNone);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoEcho()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("ECHO"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	if (keyword.CompareF(_L("OFF"))==0)
sl@0: 		{
sl@0: 		iEcho=EFalse;
sl@0: 		iScript.WriteLine(_L("Echo is off"));
sl@0: 		}
sl@0: 	else if (keyword.CompareF(_L("ON"))==0)
sl@0: 		{
sl@0: 		iEcho=ETrue;
sl@0: 		iScript.WriteLine(_L("Echo is on"));
sl@0: 		}
sl@0: 	else
sl@0: 		FatalError(_L("Expected ON|OFF to follow ECHO statement"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoWindow()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("WINDOW"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	if (keyword.CompareF(_L("OFF"))==0)
sl@0: 		{
sl@0: 		iWindow=EFalse;
sl@0: 		iScript.WriteLine(_L("Window is off"));
sl@0: 		}
sl@0: 	else if (keyword.CompareF(_L("ON"))==0)
sl@0: 		{
sl@0: 		iWindow=ETrue;
sl@0: 		iScript.WriteLine(_L("Window is on"));
sl@0: 		}
sl@0: 	else
sl@0: 		FatalError(_L("Expected ON|OFF to follow WINDOW statement"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoAccess()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("ACCESS"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	if (keyword.CompareF(_L("UPDATE"))==0)
sl@0: 		{
sl@0: 		iAccess=RDbRowSet::EUpdatable;
sl@0: 		iScript.WriteLine(_L("Access is updateable"));
sl@0: 		}
sl@0: 	else if (keyword.CompareF(_L("READ"))==0)
sl@0: 		{
sl@0: 		iAccess=RDbRowSet::EReadOnly;
sl@0: 		iScript.WriteLine(_L("Access is read only"));
sl@0: 		}
sl@0: 	else if (keyword.CompareF(_L("INSERT"))==0)
sl@0: 		{
sl@0: 		iAccess=RDbRowSet::EInsertOnly;
sl@0: 		iScript.WriteLine(_L("Access is insert only"));
sl@0: 		}
sl@0: 	else
sl@0: 		FatalError(_L("Expected UPDATE|INSERT|READ to follow ACCESS statement"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoResultsL()
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken token;
sl@0: 	iScript.GetNextTokenFromLine(token);
sl@0: 	test(token.CompareF(_L("RESULTS"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromLine(token);
sl@0: 	if (token.Compare(_L("{"))!=0)		
sl@0: 		FatalError(_L("missing '{'"));
sl@0: 	iScript.GetNextTokenFromLine(token);					// first value
sl@0: 	TLex value;
sl@0: 	RDbRowSet& rowset=iResults.iView;
sl@0: 	CDbColSet* colset=rowset.ColSetL();
sl@0: 	CleanupStack::PushL(colset);
sl@0: 	TDbColNo colno=colset->ColNo(KRowIdColName);
sl@0: 	CArrayFixFlat<TInt>* rowIdScript=new CArrayFixFlat<TInt>(4);
sl@0: 	CleanupStack::PushL(rowIdScript);
sl@0: 	CArrayFixFlat<TInt>* rowIdView=new CArrayFixFlat<TInt>(4);
sl@0: 	CleanupStack::PushL(rowIdView);
sl@0: 	rowset.BeginningL();
sl@0: 	while (rowset.NextL())				
sl@0: 		{
sl@0: 		rowset.GetL();
sl@0: 		TUint rIdScript;
sl@0: 		value=token;
sl@0: 		if (value.Val(rIdScript)!=KErrNone)
sl@0: 			{
sl@0: 			TScriptLine line;
sl@0: 			line.Format(_L("Unable to extract row id from \"%S\""),&token);
sl@0: 			FatalError(line);
sl@0: 			}
sl@0: 		TUint rIdView=rowset.ColUint(colno);
sl@0: 		rowIdScript->AppendL(rIdScript);
sl@0: 		rowIdView->AppendL(rIdView);
sl@0: 		iScript.GetNextTokenFromLine(token);			
sl@0: 		if (token.Compare(_L(","))==0 || token.Compare(_L("}"))==0)
sl@0: 			{
sl@0: 			if (rowIdScript->Count())
sl@0: 				{
sl@0: 				TKeyArrayFix key(0,ECmpTInt);
sl@0: 				rowIdScript->Sort(key);
sl@0: 				rowIdView->Sort(key);
sl@0: 				for (TInt ii=0;ii<rowIdScript->Count();++ii)
sl@0: 					{
sl@0: 					TInt expectedId=(*rowIdScript)[ii];
sl@0: 					TInt actualId=(*rowIdView)[ii];
sl@0: 					if (actualId!=expectedId)
sl@0: 						{
sl@0: 						TScriptLine line;
sl@0: 						line.Format(_L("expected row id %d, actual row id %d"),actualId,expectedId);
sl@0: 						FatalError(line);
sl@0: 						}
sl@0: 					}
sl@0: 				rowIdScript->Reset();
sl@0: 				rowIdView->Reset();
sl@0: 				}
sl@0: 			if (token.Compare(_L(","))==0)
sl@0: 				iScript.GetNextTokenFromLine(token);
sl@0: 			}
sl@0: 		}
sl@0: 	if (token.Compare(_L("}"))!=0)
sl@0: 		FatalError(_L("too many results expected"));
sl@0: 	CleanupStack::PopAndDestroy(3);	// arrays + colset
sl@0: 	iScript.ConsumeStatement();
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoBuildTable()
sl@0: //
sl@0: // same as Sql create statement, but adds a counter
sl@0: //
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("BUILD"))==0);
sl@0: 	//
sl@0: 	TScriptLine sql(_L("CREATE "));
sl@0: 	sql.Append(iScript.Statement());
sl@0: 	TInt pos=sql.Find(_L("("));
sl@0: 	sql.Insert(++pos,_L("Rw COUNTER,"));
sl@0: 	iScript.ConsumeStatement();
sl@0: 	ExecuteSql(sql);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoQuery()
sl@0: //
sl@0: // same as Sql select statement, but makes sure counter is included
sl@0: //
sl@0: 	{
sl@0: 	// test its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("QUERY"))==0);
sl@0: 	//
sl@0: 	TScriptLine sql(iScript.Statement());
sl@0: 	if (sql.Find(_L("*"))!=0)
sl@0: 		{
sl@0: 		sql.Insert(0,_L(","));
sl@0: 		sql.Insert(0,KRowIdColName);
sl@0: 		}
sl@0: 	sql.Insert(0,_L("SELECT "));
sl@0: 	iScript.ConsumeStatement();
sl@0: 	ExecuteSql(sql);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::FatalError(const TDesC& aLine)
sl@0: 	{
sl@0: 	iScript.WriteError(aLine);
sl@0: 	test(0);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::FatalError()
sl@0: 	{
sl@0: 	FatalError(_L("wrong expected value"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::FatalSqlError(const TDesC& aLine)
sl@0: 	{
sl@0: 	iScript.WriteSqlError(iResults,aLine);
sl@0: 	test(0);
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoPopulate()
sl@0: 	{
sl@0: 	// check its right function
sl@0: 	TScriptToken token;
sl@0: 	iScript.GetNextTokenFromLine(token);
sl@0: 	test(token.CompareF(_L("POPULATE"))==0);
sl@0: 	//
sl@0: 	TScriptLine sqlbase=_L("INSERT INTO ");
sl@0: 	iScript.GetNextTokenFromLine(token);	// table name
sl@0: 	sqlbase.AppendFormat(_L("%S "),&token);	
sl@0: 	iScript.GetNextTokenFromLine(token);
sl@0: 	if (token.Compare(_L("("))==0)			// optional column names present?
sl@0: 		{			
sl@0: 		for (;;) 							
sl@0: 			{
sl@0: 			sqlbase.AppendFormat(token);
sl@0: 			if (token.Compare(_L(")"))==0)
sl@0: 				break;
sl@0: 			iScript.GetNextTokenFromLine(token);		
sl@0: 			} 
sl@0: 		iScript.GetNextTokenFromLine(token);
sl@0: 		}
sl@0: 	if (token.Compare(_L("{"))!=0)		
sl@0: 		FatalError(_L("missing '{'"));
sl@0: 	sqlbase.AppendFormat(_L(" VALUES ("));
sl@0: 	iScript.GetNextTokenFromLine(token);	// first value
sl@0: 	TheDatabase.Begin();					// all in same transaction
sl@0: 	for (;;)
sl@0: 		{
sl@0: 		if (token.Compare(_L("}"))==0)	
sl@0: 			break;
sl@0: 		TScriptLine sql=sqlbase;
sl@0: 		for (;;)
sl@0: 			{
sl@0: 			sql.Append(token);
sl@0: 			iScript.GetNextTokenFromLine(token);
sl@0: 			if (token.Compare(_L(","))==0)
sl@0: 				{
sl@0: 				sql.Append(token);			// comma
sl@0: 				iScript.GetNextTokenFromLine(token);
sl@0: 				}
sl@0: 			else
sl@0: 				break;
sl@0: 			}
sl@0: 		sql.AppendFormat(_L(")"));
sl@0: 		ExecuteSql(sql);
sl@0: 		TestForNoError();
sl@0: 		}
sl@0: 	TheDatabase.Commit();
sl@0: 	iScript.ConsumeStatement();
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoPrintL() 
sl@0: 	{
sl@0: 	// check its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	test(keyword.CompareF(_L("PRINT"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromStatement(keyword);
sl@0: 	if (keyword.CompareF(_L("VIEW"))==0)
sl@0: 		PrintL(iResults.iView);
sl@0: 	else if (keyword.CompareF(_L("TABLE"))==0)
sl@0: 		{
sl@0: 		iScript.GetNextTokenFromStatement(keyword);	// name of table
sl@0: 		RDbTable table;
sl@0: 		TInt err=table.Open(TheDatabase,keyword,table.EReadOnly);
sl@0: 		if (err!=KErrNone)
sl@0: 			FatalError(_L("unable to open table"));
sl@0: 		PrintL(table);
sl@0: 		table.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		FatalError(_L("expected VIEW or TABLE keyword not present"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::DoCompareL() 
sl@0: 	{
sl@0: 	// check its right function
sl@0: 	TScriptToken keyword;
sl@0: 	iScript.GetNextTokenFromLine(keyword);
sl@0: 	test(keyword.CompareF(_L("COMPARE"))==0);
sl@0: 	//
sl@0: 	iScript.GetNextTokenFromLine(keyword);
sl@0: 	if (keyword.CompareF(_L("VIEW"))==0)
sl@0: 		CompareL(iResults.iView);
sl@0: 	else if (keyword.CompareF(_L("TABLE"))==0)
sl@0: 		{
sl@0: 		iScript.GetNextTokenFromLine(keyword);	// name of table
sl@0: 		RDbTable table;
sl@0: 		TInt err=table.Open(TheDatabase,keyword,table.EReadOnly);
sl@0: 		if (err!=KErrNone)
sl@0: 			FatalError(_L("unable to open table"));
sl@0: 		CompareL(table);
sl@0: 		table.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		FatalError(_L("expected VIEW or TABLE keyword not present"));
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::CompareL(RDbRowSet& aRowSet) 
sl@0: 	{
sl@0: 	TScriptToken token;
sl@0: 	iScript.GetNextTokenFromLine(token);
sl@0: 	TBool rowIdMode=EFalse;
sl@0: 	CArrayFixFlat<TInt>* rowIdToTest=new CArrayFixFlat<TInt>(4);
sl@0: 	CleanupStack::PushL(rowIdToTest);
sl@0: 	if (token.Compare(_L("("))==0)				// optional row ids present?
sl@0: 		{
sl@0: 		rowIdMode=ETrue;
sl@0: 		iScript.GetNextTokenFromLine(token);	// first value
sl@0: 		TLex value;
sl@0: 		TInt rowId;
sl@0: 		for (;;) 							
sl@0: 			{
sl@0: 			value=token;
sl@0: 			test (value.Val(rowId)==KErrNone);
sl@0: 			rowIdToTest->AppendL(rowId);		// add row id to array
sl@0: 			iScript.GetNextTokenFromLine(token);
sl@0: 			if (token.Compare(_L(")"))==0)
sl@0: 				break;
sl@0: 			if (token.Compare(_L(","))==0)
sl@0: 				iScript.GetNextTokenFromLine(token);					
sl@0: 			} 
sl@0: 		iScript.GetNextTokenFromLine(token);
sl@0: 		}
sl@0: 	if (token.Compare(_L("{"))!=0)		
sl@0: 		FatalError(_L("missing '{'"));
sl@0: 	TInt columns=aRowSet.ColCount();
sl@0: 	CDbColSet* colset=aRowSet.ColSetL();
sl@0: 	aRowSet.BeginningL();
sl@0: 	while (aRowSet.NextL())
sl@0: 		{
sl@0: 		aRowSet.GetL();
sl@0: 		if (rowIdMode)
sl@0: 			{
sl@0: 			TInt currentId=aRowSet.ColUint(colset->ColNo(KRowIdColName));
sl@0: 			TBool toTest=EFalse;
sl@0: 			for (TInt jj=0; jj<rowIdToTest->Count(); ++jj)
sl@0: 				{
sl@0: 				if (currentId==(*rowIdToTest)[jj])
sl@0: 					toTest=ETrue;
sl@0: 				}
sl@0: 			if (!toTest)
sl@0: 				continue;
sl@0: 			}
sl@0: 		for (TInt ii=1;ii<=columns;++ii)
sl@0: 			{
sl@0: 			if (rowIdMode && ii==colset->ColNo(KRowIdColName))	// ignore row id column
sl@0: 				continue;
sl@0: 			const TDbCol& col=(*colset)[ii];
sl@0: 			iScript.GetNextTokenFromLine(token);				// value
sl@0: 			if (token.Compare(_L(","))==0)
sl@0: 				iScript.GetNextTokenFromLine(token);			// ignore comma
sl@0: 			if (aRowSet.IsColNull(ii))
sl@0: 				{
sl@0: 				if (token.CompareF(_L("NULL"))!=0)
sl@0: 					FatalError(_L("NULL expected"));
sl@0: 				continue;
sl@0: 				}
sl@0: 			CompareValues(aRowSet,ii,col.iType,token); 
sl@0: 			}
sl@0: 		}
sl@0: 	delete colset;
sl@0: 	CleanupStack::PopAndDestroy();				// rowIdToTest
sl@0: 	iScript.GetNextTokenFromLine(token);		// look for closing '}'
sl@0: 	if (token.Compare(_L("}"))!=0)		
sl@0: 		FatalError(_L("missing '}'"));
sl@0: 	iScript.ConsumeStatement();
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::CompareValues(RDbRowSet& aRowSet,TDbColNo ColNo,TDbColType aType,const TDesC& aToken) 
sl@0: //
sl@0: // compares the value from a rowset aRowset, colimn number aColNo and of type aType, with the value
sl@0: // contained in the descriptor aToken
sl@0: //
sl@0: 	{
sl@0: 	TLex value=aToken;
sl@0: 	switch (aType)
sl@0: 		{
sl@0: 	case EDbColInt32:
sl@0: 		{
sl@0: 		TInt num;
sl@0: 		test (value.Val(num)==KErrNone);
sl@0: 		if (num!=aRowSet.ColInt(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColInt8:
sl@0: 		{
sl@0: 		TInt8 num8;
sl@0: 		test (value.Val(num8)==KErrNone);
sl@0: 		if (num8!=aRowSet.ColInt8(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColInt16:
sl@0: 		{
sl@0: 		TInt16 num16;
sl@0: 		test (value.Val(num16)==KErrNone);
sl@0: 		if (num16!=aRowSet.ColInt16(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColInt64:
sl@0: 		{
sl@0: 		TInt64 num64;
sl@0: 		test (value.Val(num64)==KErrNone);
sl@0: 		if (num64!=aRowSet.ColInt64(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColUint8:
sl@0: 		{
sl@0: 		TUint8 numu8;
sl@0: 		test (value.Val(numu8,EDecimal)==KErrNone);
sl@0: 		if (numu8!=aRowSet.ColUint8(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColUint16:
sl@0: 		{
sl@0: 		TUint16 numu16;
sl@0: 		test (value.Val(numu16,EDecimal)==KErrNone);
sl@0: 		if (numu16!=aRowSet.ColUint16(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColUint32:
sl@0: 		{
sl@0: 		TUint32 numu32;
sl@0: 		test (value.Val(numu32,EDecimal)==KErrNone);
sl@0: 		if (numu32!=aRowSet.ColUint32(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColReal32:
sl@0: 		{
sl@0: 		TReal32 numr32;
sl@0: 		test (value.Val(numr32)==KErrNone);
sl@0: 		if (numr32!=aRowSet.ColReal32(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColReal64:
sl@0: 		{
sl@0: 		TReal64 numr64;
sl@0: 		test (value.Val(numr64)==KErrNone);
sl@0: 		if (numr64!=aRowSet.ColReal64(ColNo))
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColText8:
sl@0: 	case EDbColText16:
sl@0: 		{
sl@0: 		TPtrC text=aToken.Mid(1,aToken.Length()-2);			// skip quotes
sl@0: 		if (text.CompareF(aRowSet.ColDes(ColNo))!=0)
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	case EDbColDateTime:
sl@0: 		{
sl@0: 		TScriptLine time=aToken.Mid(1,aToken.Length()-2);	// skip hashes
sl@0: 		TTime t1;
sl@0: 		t1.Parse(time);
sl@0: 		TTime t2(aRowSet.ColTime(ColNo).DateTime());
sl@0: 		if (t1!=t2)
sl@0: 			FatalError();
sl@0: 		break;
sl@0: 		}
sl@0: 	default:
sl@0: 		break;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void TScriptEngine::PrintL(RDbRowSet& aRowSet) 
sl@0: 	{
sl@0: 	iScript.WriteLine(TPtrC());
sl@0: 	TInt columns=aRowSet.ColCount();	
sl@0: 	CDbColSet* colset=aRowSet.ColSetL();
sl@0: 	TScriptLine line;
sl@0: 	for (TInt i=1;i<=columns;++i)
sl@0: 		{
sl@0: 		const TDbCol& col=(*colset)[i];
sl@0: 		line.AppendFormat(_L("%S\t"),&col.iName);
sl@0: 		}
sl@0: 	iScript.WriteLine(line);
sl@0: 	aRowSet.BeginningL();
sl@0: 	while (aRowSet.NextL())
sl@0: 		{
sl@0: 		line=TPtrC();
sl@0: 		for (TInt ii=1;ii<=columns;++ii)
sl@0: 			{
sl@0: 			const TDbCol& col=(*colset)[ii];
sl@0: 			aRowSet.GetL();
sl@0: 			if (aRowSet.IsColNull(ii))
sl@0: 				{
sl@0: 				line.AppendFormat(_L("NULL\t"));
sl@0: 				continue;
sl@0: 				}
sl@0: 			switch (col.iType)
sl@0: 				{
sl@0: 			case EDbColInt32:
sl@0: 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt(ii));
sl@0: 				break;
sl@0: 			case EDbColInt8:
sl@0: 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt8(ii));
sl@0: 				break;
sl@0: 			case EDbColInt16:
sl@0: 				line.AppendFormat(_L("%d\t"),aRowSet.ColInt16(ii));
sl@0: 				break;
sl@0: 			case EDbColInt64:
sl@0: 				line.AppendFormat(_L("%ld\t"),aRowSet.ColInt64(ii));
sl@0: 				break;
sl@0: 			case EDbColUint8:
sl@0: 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint8(ii));
sl@0: 				break;
sl@0: 			case EDbColUint16:
sl@0: 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint16(ii));
sl@0: 				break;
sl@0: 			case EDbColUint32:
sl@0: 				line.AppendFormat(_L("%u\t"),aRowSet.ColUint(ii));
sl@0: 				break;
sl@0: 			case EDbColReal32:
sl@0: 				line.AppendFormat(_L("%f\t"),aRowSet.ColReal32(ii));
sl@0: 				break;
sl@0: 			case EDbColReal64:
sl@0: 				line.AppendFormat(_L("%f\t"),aRowSet.ColReal64(ii));
sl@0: 				break;
sl@0: 			case EDbColText:
sl@0: 				line.Append(aRowSet.ColDes(ii));
sl@0: 				line.Append('\t');
sl@0: 				break;
sl@0: 			case EDbColDateTime:
sl@0: 				{
sl@0: 				TDateTime time(aRowSet.ColTime(ii).DateTime());
sl@0: 				line.AppendFormat(_L("%d:%d:%d %d/%d/%d"),time.Hour(),time.Minute(),time.Second(),time.Day(),time.Month(),time.Year());
sl@0: 				}	
sl@0: 				break;
sl@0: 			case EDbColLongText:
sl@0: 				{
sl@0: 				RDbColReadStream blob;
sl@0: 				blob.OpenLC(aRowSet,ii);
sl@0: 				TScriptLine text;
sl@0: 				blob.ReadL(text,aRowSet.ColLength(ii));
sl@0: 				CleanupStack::PopAndDestroy();
sl@0: 				line.AppendFormat(_L("%S\t"),&text);
sl@0: 				}
sl@0: 			default:
sl@0: 				break;
sl@0: 				}
sl@0: 			}
sl@0: 		iScript.WriteLine(line);
sl@0: 		}
sl@0: 	iScript.WriteLine(TPtrC());
sl@0: 	delete colset;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: LOCAL_C void CreateDatabaseL()
sl@0: //
sl@0: // Create the database
sl@0: //
sl@0: 	{
sl@0: 	test(TheDatabase.Replace(TheFs,KTestDatabase)==KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void CloseDatabase()
sl@0: //
sl@0: // Close the database
sl@0: //
sl@0: 	{
sl@0: 	TheDatabase.Close();
sl@0: 
sl@0: 	TInt err = TheCrcChecker.GenerateCrcL(KTestDatabase);
sl@0: 	test(err==KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void SetupTestDirectory()
sl@0: //
sl@0: // Prepare the test directory.
sl@0: //
sl@0:     {
sl@0: 	TInt err=TheFs.Connect();
sl@0: 	test(err==KErrNone);
sl@0: //
sl@0: 	err=TheFs.MkDir(KTestDatabase);
sl@0: 	test(err==KErrNone || err==KErrAlreadyExists);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void SetupCleanup()
sl@0: //
sl@0: // Initialise the cleanup stack.
sl@0: //
sl@0:     {
sl@0: 	TheTrapCleanup=CTrapCleanup::New();
sl@0: 	test(TheTrapCleanup!=NULL);
sl@0: 	TRAPD(err,\
sl@0: 		{\
sl@0: 		for (TInt i=KTestCleanupStack;i>0;i--)\
sl@0: 			CleanupStack::PushL((TAny*)0);\
sl@0: 		CleanupStack::Pop(KTestCleanupStack);\
sl@0: 		});
sl@0: 	test(err==KErrNone);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0632
sl@0: @SYMTestCaseDesc        Executes the script files
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Start the script engine 
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void RunScriptL()
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0632 Running script "));
sl@0: 	CreateDatabaseL();
sl@0: 	TScriptEngine script;
sl@0: 	script.RunL();
sl@0: 	CloseDatabase();
sl@0: 	TheView.Close();
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void DeleteDataFile(const TDesC& aFullName)
sl@0: 	{
sl@0: 	RFs fsSession;
sl@0: 	TInt err = fsSession.Connect();
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		TEntry entry;
sl@0: 		if(fsSession.Entry(aFullName, entry) == KErrNone)
sl@0: 			{
sl@0: 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
sl@0: 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			err = fsSession.Delete(aFullName);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			}
sl@0: 		fsSession.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: GLDEF_C TInt E32Main()
sl@0:     {
sl@0: 	test.Title();
sl@0: 	SetupTestDirectory();
sl@0: 	SetupCleanup();
sl@0: 	__UHEAP_MARK;
sl@0: //
sl@0: 	TRAPD(err,RunScriptL());
sl@0: 	test(err==KErrNone);
sl@0: 
sl@0: 	//deletion of data files must be done before call to end - DEF047652
sl@0: 	::DeleteDataFile(KTestDatabase);
sl@0: 	::DeleteDataFile(KOutputFile);//Comment this line if you want topo keep t_script.log file.	
sl@0: 	
sl@0: 
sl@0: #ifndef __linux__
sl@0: #ifndef __TOOLS2__ 
sl@0: 	TRAPD(lc, err = TheCrcChecker.DumpCrcRecordsL(KCrcRecord));
sl@0: 	test(err==KErrNone);
sl@0: 	test(lc==KErrNone);
sl@0: #else
sl@0: 	TRAPD(lc, err = TheCrcChecker.ValidateCrcRecordsL(KCrcRecord));
sl@0: 	TPtrC errmsg;
sl@0: 	TheCrcChecker.ErrorReportL(err, errmsg);
sl@0: 	RDebug::Print(errmsg);
sl@0: 	test(err==KErrNone || err==TDBMS_CRCChecks::ECrcCheckOk);
sl@0: #endif
sl@0: #endif
sl@0: 	
sl@0: 	test.End();
sl@0: //
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	delete TheTrapCleanup;
sl@0: 
sl@0: 	TheFs.Close();
sl@0: 	test.Close();
sl@0: 
sl@0: 	return 0;
sl@0:     }