--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/TEST/t_sqlapi2.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1744 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32test.h>
+#include <e32math.h>
+#include <bautils.h>
+#include <s32buf.h> //MStreamBuf
+#include <sqldb.h>
+#include "SqlResourceProfiler.h"
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+RTest TheTest(_L("t_sqlapi2 test"));
+RSqlDatabase TheDb;
+RSqlStatement TheStmt;
+
+_LIT(KTestDir, "c:\\test\\");
+_LIT(KTestDbName1, "c:\\test\\t_sqlapi2_1.db");
+_LIT(KTestDbName2, "c:\\private\\1111C1EF\\t_sqlapi2_2.db");//t_sqlapi2 app - private database
+
+_LIT(KDbInjectedName1, "DELETE FROM symbian_settings;c:\\test\\A.db");
+_LIT(KDbInjectedName2, "c:\\test\\A.db;DELETE FROM symbian_settings;");
+
+const TInt KBufLen = 8192;
+TBuf<KBufLen> TheBuf;
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void DeleteTestFiles()
+ {
+ TheStmt.Close();
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KDbInjectedName2);
+ (void)RSqlDatabase::Delete(KDbInjectedName1);
+ (void)RSqlDatabase::Delete(KTestDbName2);
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+//Test macros and functions
+void Check(TInt aValue, TInt aLine)
+ {
+ if(!aValue)
+ {
+ DeleteTestFiles();
+ TheTest(EFalse, aLine);
+ }
+ }
+void Check(TInt aValue, TInt aExpected, TInt aLine)
+ {
+ if(aValue != aExpected)
+ {
+ DeleteTestFiles();
+ RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
+ TheTest(EFalse, aLine);
+ }
+ }
+#define TEST(arg) ::Check((arg), __LINE__)
+#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void CreateTestEnv()
+ {
+ RFs fs;
+ TInt err = fs.Connect();
+ TEST2(err, KErrNone);
+
+ err = fs.MkDir(KTestDir);
+ TEST(err == KErrNone || err == KErrAlreadyExists);
+
+ err = fs.CreatePrivatePath(EDriveC);
+ TEST(err == KErrNone || err == KErrAlreadyExists);
+
+ fs.Close();
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-3512
+@SYMTestCaseDesc RSqlStatement::ColumnCount() - SELECT statements test
+ The test creates a database with a table and then checks the ColumnCount()
+ return result for the following statements:
+ - select all columns;
+ - select a subset;
+ - select an expression;
+ - select a constant;
+ - multi-table select;
+ - select a function;
+ - select plus sub-query;
+@SYMTestPriority High
+@SYMTestActions RSqlStatement::ColumnCount() test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ8035
+*/
+void ColumnCountTest()
+ {
+
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ //Create table 1
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT,Id2 INTEGER,Data BLOB)"));
+ TEST(err >= 0);
+
+ err = TheDb.Exec(_L("INSERT INTO A VALUES(1,'AAA',6234567890,x'11AAFD0C771188')"));
+ TEST2(err, 1);
+
+ //Select all columns (SELECT *)
+ err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A"));
+ TEST2(err, KErrNone);
+ TInt cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 4);
+ TheStmt.Close();
+ //Select all columns (SELECT a,b,c...)
+ err = TheStmt.Prepare(TheDb, _L("SELECT Id,Name,Id2,Data FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 4);
+ TheStmt.Close();
+ //Select column subset
+ err = TheStmt.Prepare(TheDb, _L("SELECT Id,Name,Data FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 3);
+ TheStmt.Close();
+ //Select column subset + expression
+ err = TheStmt.Prepare(TheDb, _L("SELECT Id,Id+Id2 FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 2);
+ TheStmt.Close();
+ //Select column subset + constant
+ err = TheStmt.Prepare(TheDb, _L("SELECT Id,Id2,345.78 FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 3);
+ TheStmt.Close();
+ //Select SQL function
+ err = TheStmt.Prepare(TheDb, _L("SELECT COUNT(*) FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 1);
+ TheStmt.Close();
+ //Create table 2
+ err = TheDb.Exec(_L("CREATE TABLE B(Id INTEGER, S INTEGER)"));
+ TEST(err >= 0);
+ err = TheDb.Exec(_L("INSERT INTO B VALUES(1,25)"));
+ TEST2(err, 1);
+ //Multitable select
+ err = TheStmt.Prepare(TheDb, _L("SELECT A.Id,B.S FROM A,B WHERE A.Id = B.Id"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 2);
+ TheStmt.Close();
+ //Select + Subquery
+ err = TheStmt.Prepare(TheDb, _L("SELECT Id FROM A WHERE (SELECT S FROM B WHERE A.Id = B.Id) > 10"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 1);
+ TheStmt.Close();
+ //Cleanup
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-3513
+@SYMTestCaseDesc RSqlStatement::ColumnCount() - DDL and DML statements test
+ The test creates a database with a table and then checks the ColumnCount() return result for
+ DML statements (INSERT/UPDATE/DELETE) and DDL statements (CREATE TABLE/INDEX, DROP TABLE?INDEX).
+ The column count for DML and DDL statements should be 0.
+@SYMTestPriority High
+@SYMTestActions RSqlStatement::ColumnCount() test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ8035
+*/
+void ColumnCountTest2()
+ {
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ //Create table
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT,Id2 INTEGER,Data BLOB)"));
+ TEST(err >= 0);
+ err = TheDb.Exec(_L("INSERT INTO A VALUES(1,'AAA',6234567890,x'11AAFD0C771188')"));
+ TEST2(err, 1);
+ //INSERT statement
+ err = TheStmt.Prepare(TheDb, _L("INSERT INTO A(Id,Id2) VALUES(:P1,:P2)"));
+ TEST2(err, KErrNone);
+ TInt cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //UPDATE statement
+ err = TheStmt.Prepare(TheDb, _L("UPDATE A SET Id2=100 WHERE Id=:P1"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //DELETE statement
+ err = TheStmt.Prepare(TheDb, _L("DELETE FROM A WHERE Id=:P1"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //CREATE TABLE statement
+ err = TheStmt.Prepare(TheDb, _L("CREATE TABLE B AS SELECT * FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //DROP TABLE statement
+ err = TheStmt.Prepare(TheDb, _L("DROP TABLE A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //CREATE INDEX statement
+ err = TheStmt.Prepare(TheDb, _L("CREATE INDEX I ON A(Id)"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ err = TheStmt.Exec();
+ TEST(err >= 0);
+ TheStmt.Close();
+ //DROP INDEX statement
+ err = TheStmt.Prepare(TheDb, _L("DROP INDEX I"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //CREATE TRIGGER statement
+ err = TheStmt.Prepare(TheDb,
+ _L("CREATE TRIGGER Trg BEFORE DELETE ON A \
+ BEGIN \
+ SELECT CASE WHEN ((SELECT Id2 FROM A WHERE A.Id = old.Id) > 0) \
+ THEN RAISE (ABORT, 'Id2 > 0') \
+ END;\
+ END;"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //CREATE VIEW statement
+ err = TheStmt.Prepare(TheDb, _L("CREATE VIEW V AS SELECT * FROM A"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ err = TheStmt.Exec();
+ TEST(err >= 0);
+ TheStmt.Close();
+ //DROP VIEW statement
+ err = TheStmt.Prepare(TheDb, _L("DROP VIEW V"));
+ TEST2(err, KErrNone);
+ cnt = TheStmt.ColumnCount();
+ TEST2(cnt, 0);
+ TheStmt.Close();
+ //Cleanup
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-3514
+@SYMTestCaseDesc RSqlStatement::DeclaredColumnType() test
+ The test creates a database with a table and then checks the DeclaredColumnType() return result for:
+ - select all column from the table and check their types;
+ - multi-table select plus column type checks;
+ - select expression - the expected column type is ESqlInt;
+ - select constant - the expected column type is ESqlInt;
+@SYMTestPriority High
+@SYMTestActions RSqlStatement::ColumnCount() test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ8035
+*/
+void DeclaredColumnTypeTest()
+ {
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ const char* KColTypeNames[] =
+ {"INTEGER", "LONG INTEGER", "INT", "SHORT INT", "SMALL INT", "TINY INT", "SHORT", "INT64",
+ "TEXT", "LONGTEXT", "CLOB", "CHAR", "CHARACTER(20)", "LONG TEXT",
+ "BINARY", "LONG BINARY", "LONGBINARY", "BLOB", "LONGBLOB", "LONG BLOB",
+ "REAL", "FLOAT", "DOUBLE", "LONG DOUBLE",
+ "LONG LONG", "BOO HOO"};
+ const TSqlColumnType KColTypes[] =
+ {ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,
+ ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,
+ ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,
+ ESqlReal,ESqlReal,ESqlReal,ESqlReal,
+ ESqlInt,ESqlInt};
+ const TInt KColTypeCnt = sizeof(KColTypes) / sizeof(KColTypes[0]);
+ TEST2(sizeof(KColTypeNames) / sizeof(KColTypeNames[0]), KColTypeCnt);
+ //Create table 1
+ TBuf8<512> sql;
+ sql.Copy(_L8("CREATE TABLE T("));
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ sql.Append(TChar('A'));
+ sql.AppendNum(i + 1);
+ sql.Append(TChar(' '));
+ sql.Append((TUint8*)KColTypeNames[i], User::StringLength((TUint8*)KColTypeNames[i]));
+ sql.Append(TChar(','));
+ }
+ sql.Replace(sql.Length() - 1, 1, _L8(")"));
+ err = TheDb.Exec(sql);
+ TEST(err >= 0);
+ //Select all columns (SELECT *)
+ err = TheStmt.Prepare(TheDb, _L("SELECT * FROM T"));
+ TEST2(err, KErrNone);
+ TInt cnt = TheStmt.ColumnCount();
+ TEST2(cnt, KColTypeCnt);
+ TSqlColumnType colType;
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ TInt err = TheStmt.DeclaredColumnType(i, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, KColTypes[i]);
+ }
+ TheStmt.Close();
+ //Create table 2
+ err = TheDb.Exec(_L8("CREATE TABLE T2(Id INTEGER, DATA BLOB)"));
+ TEST(err >= 0);
+ //Multi-table select
+ err = TheStmt.Prepare(TheDb, _L("SELECT T.A1,T2.Id,T.A9,T2.Data FROM T,T2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.DeclaredColumnType(0, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlInt);
+ err = TheStmt.DeclaredColumnType(1, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlInt);
+ err = TheStmt.DeclaredColumnType(2, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlText);
+ err = TheStmt.DeclaredColumnType(3, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlBinary);
+ TheStmt.Close();
+ //Select expression
+ err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES FROM t2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.DeclaredColumnType(0, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlInt);
+ TheStmt.Close();
+ //Select constant
+ err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES, 55.89 FROM t2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.DeclaredColumnType(1, colType);
+ TEST2(err, KErrNone);
+ TEST2(colType, ESqlInt);
+ TheStmt.Close();
+ //Cleanup
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4017
+@SYMTestCaseDesc RSqlStatement::ColumnName(TInt, TPtrC&) test
+ The test creates a database with a table and then checks the ColumnName() return result for:
+ - select all column from the table and check their names;
+ - multi-table select plus column name checks;
+ - select expression - the expected column name is RES
+ - select constant - the expected column type is 55.89
+@SYMTestPriority High
+@SYMTestActions RSqlStatement::ColumnName() test
+@SYMTestExpectedResults Test must not fail
+@SYMCR RMAD-7B7EV5
+ Add SQL Server APIs to retrieve column and parameter names
+*/
+void ColumnNameTest()
+ {
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ const char* KColTypeNames[] =
+ {"INTEGER", "LONG INTEGER", "INT", "SHORT INT", "SMALL INT", "TINY INT", "SHORT", "INT64",
+ "TEXT", "LONGTEXT", "CLOB", "CHAR", "CHARACTER(20)", "LONG TEXT",
+ "BINARY", "LONG BINARY", "LONGBINARY", "BLOB", "LONGBLOB", "LONG BLOB",
+ "REAL", "FLOAT", "DOUBLE", "LONG DOUBLE",
+ "LONG LONG", "BOO HOO"};
+ const TSqlColumnType KColTypes[] =
+ {ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,
+ ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,
+ ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,
+ ESqlReal,ESqlReal,ESqlReal,ESqlReal,
+ ESqlInt,ESqlInt};
+ const TInt KColTypeCnt = sizeof(KColTypes) / sizeof(KColTypes[0]);
+ TEST2(sizeof(KColTypeNames) / sizeof(KColTypeNames[0]), KColTypeCnt);
+ //Create table 1
+ TBuf8<512> sql;
+ sql.Copy(_L8("CREATE TABLE T("));
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ sql.Append(TChar('A'));
+ sql.AppendNum(i + 1);
+ sql.Append(TChar(' '));
+ sql.Append((TUint8*)KColTypeNames[i], User::StringLength((TUint8*)KColTypeNames[i]));
+ sql.Append(TChar(','));
+ }
+ sql.Replace(sql.Length() - 1, 1, _L8(")"));
+ err = TheDb.Exec(sql);
+ TEST(err >= 0);
+ //Select all columns (SELECT *)
+ err = TheStmt.Prepare(TheDb, _L("SELECT * FROM T"));
+ TEST2(err, KErrNone);
+ TInt cnt = TheStmt.ColumnCount();
+ TEST2(cnt, KColTypeCnt);
+ TPtrC colName;
+ TBuf<128> expectedColName;
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ expectedColName.Zero();
+ expectedColName.Append(TChar('A'));
+ expectedColName.AppendNum(i + 1);
+ TInt err = TheStmt.ColumnName(i, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(expectedColName), 0);
+ TSqlColumnType type;
+ err = TheStmt.DeclaredColumnType(i, type);
+ TEST2(err, KErrNone);
+ TEST2(type, KColTypes[i]);
+ }
+ TheStmt.Close();
+ //Create table 2
+ err = TheDb.Exec(_L8("CREATE TABLE T2(Id INTEGER, DATA BLOB)"));
+ TEST(err >= 0);
+ //Multi-table select
+ err = TheStmt.Prepare(TheDb, _L("SELECT T.A1,T2.Id,T.A9,T2.DATA FROM T,T2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.ColumnName(0, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("A1")), 0);
+ err = TheStmt.ColumnName(1, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("Id")), 0);
+ err = TheStmt.ColumnName(2, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("A9")), 0);
+ err = TheStmt.ColumnName(3, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("DATA")), 0);
+ TheStmt.Close();
+ //Select expression
+ err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES FROM t2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.ColumnName(0, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("RES")), 0);
+ TheStmt.Close();
+ //Select constant
+ err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES, 55.89 FROM t2"));
+ TEST2(err, KErrNone);
+ err = TheStmt.ColumnName(1, colName);
+ TEST2(err, KErrNone);
+ TEST2(colName.Compare(_L("55.89")), 0);
+ TheStmt.Close();
+ //Cleanup
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4018
+@SYMTestCaseDesc RSqlStatement::ParameterName(TInt, TPtrC&) and RSqlStatement::ParamName(TInt, TPtrC&) test
+ DML test:
+ The test creates a database with a table and prepares an insert query.
+ The test then checks the ParameterName() and ParamName() return result for:
+ - Named parameters - return the named param
+ - Unnamed parameters - return ?<param-index>
+@SYMTestPriority High
+@SYMTestActions RSqlStatement::ParameterName() and RSqlStatement::ParamName() test
+@SYMTestExpectedResults Test must not fail
+@SYMCR RMAD-7B7EV5
+ Add SQL Server APIs to retrieve column and parameter names
+*/
+void ParamNameTest()
+ {
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ const char* KColTypeNames[] =
+ {"INTEGER", "TEXT"};
+ const TInt KColTypeCnt = sizeof(KColTypeNames) / sizeof(KColTypeNames[0]);
+ //Create table 1
+ TBuf8<256> sql;
+ sql.Copy(_L8("CREATE TABLE T("));
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ sql.Append(TChar('A'));
+ sql.AppendNum(i + 1);
+ sql.Append(TChar(' '));
+ sql.Append((TUint8*)KColTypeNames[i], User::StringLength((TUint8*)KColTypeNames[i]));
+ sql.Append(TChar(','));
+ }
+ sql.Replace(sql.Length() - 1, 1, _L8(")"));
+ err = TheDb.Exec(sql);
+ TEST(err >= 0);
+ TheStmt.Close();
+
+ // Create insert statement, then check param names
+ err = TheStmt.Prepare(TheDb, _L("INSERT INTO T (A1, A2) VALUES (:prm1, :prm2)"));
+ TEST2(err, KErrNone);
+ TPtrC paramName;
+ TBuf<128> expectedParamName;
+ for(TInt i=0;i<KColTypeCnt;++i)
+ {
+ expectedParamName.Zero();
+ expectedParamName.Append(_L(":prm"));
+ expectedParamName.AppendNum(i + 1);
+ TInt paramIndex = TheStmt.ParameterIndex(expectedParamName);
+ TEST2(paramIndex, i);
+ TInt err = TheStmt.ParameterName(i, paramName);
+ TEST2(err, KErrNone);
+ TEST2(paramName.Compare(expectedParamName), 0);
+ err = TheStmt.ParamName(i, paramName);
+ TEST2(err, KErrNone);
+ TEST2(paramName.Compare(expectedParamName), 0);
+ }
+ TheStmt.Close();
+
+ // Create insert statement, then check param names
+ err = TheStmt.Prepare(TheDb, _L("INSERT INTO T (A1, A2) VALUES (:prm1, ?)"));
+ TEST2(err, KErrNone);
+
+ expectedParamName.Zero();
+ expectedParamName.Append(_L(":prm1"));
+ TInt paramIndex = TheStmt.ParameterIndex(expectedParamName);
+ TEST2(paramIndex, 0);
+ err = TheStmt.ParameterName(0, paramName);
+ TEST2(err, KErrNone);
+ TEST2(paramName.Compare(expectedParamName), 0);
+ err = TheStmt.ParamName(0, paramName);
+ TEST2(err, KErrNone);
+ TEST2(paramName.Compare(expectedParamName), 0);
+
+ expectedParamName.Zero();
+ expectedParamName.Append(_L("?1"));
+ err = TheStmt.ParameterName(1, paramName);
+ TEST2(err, KErrNone);
+ paramIndex = TheStmt.ParameterIndex(expectedParamName);
+ TEST2(paramIndex, 1);
+ TEST2(paramName.Compare(expectedParamName), 0);
+
+ err = TheStmt.ParamName(1, paramName);
+ TEST2(err, KErrNone);
+ TEST2(paramName.Compare(expectedParamName), 0);
+
+ TheStmt.Close();
+
+ //Cleanup
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4006
+@SYMTestCaseDesc Test for DEF115300 - SqlSrv.EXE::!SQL Server when preparing invalid LEFT JOIN sql query.
+ The test does the following steps:
+ 1) Creates a 16-bit database and using 16-bit queries proves that the "GROUP BY GROUP BY" syntax error
+ does not cause an assert inside the SQLITE code.
+ 2) Creates a 8-bit database and using 8-bit queries proves that the "GROUP BY GROUP BY" syntax error
+ does not cause an assert inside the SQLITE code.
+@SYMTestPriority Medium
+@SYMTestActions Test for DEF115300 - SqlSrv.EXE::!SQL Server when preparing invalid LEFT JOIN sql query.
+@SYMTestExpectedResults Test must not fail
+@SYMDEF DEF115300
+*/
+void DEF115300()
+ {
+
+ //Step 1: 16-bit statements
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+
+ err = TheDb.Exec(_L("CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER, F2 BLOB)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO MAIN(Id,Id1) VALUES(2,3)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO MAIN(Id,Id1) VALUES(3,4)"));
+ TEST2(err, 1);
+
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER, Id1 INTEGER, F2 BLOB)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO A(Id, Id1) VALUES(2,3)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO A(Id, Id1) VALUES(4,4)"));
+ TEST2(err, 1);
+
+ err = TheDb.Exec(_L("CREATE TABLE B(Id INTEGER, Id1 INTEGER, F2 BLOB)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO B(Id, Id1) VALUES(2,3)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO B(Id, Id1) VALUES(5,4)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO B(Id, Id1) VALUES(5,4)"));
+ TEST2(err, 1);
+
+ err = TheDb.Exec(_L("CREATE VIEW v2 AS SELECT Id,Id1,F2 FROM B"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("CREATE VIEW v1 AS SELECT Id,Id1,F2 FROM A"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("CREATE VIEW v3 AS SELECT Id,Id1,F2 FROM B"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, _L("SELECT * FROM v2 LEFT JOIN MAIN ON v2.Id = MAIN.Id LEFT JOIN A ON MAIN.Id = A.Id GROUP BY GROUP BY MAIN.Id"));
+ stmt.Close();
+ TEST(err != KErrNone && err != KErrServerTerminated);
+
+ TheDb.Close();
+ err = RSqlDatabase::Delete(KTestDbName1);
+ TEST2(err, KErrNone);
+
+ //Step 2: 8-bit statements
+ _LIT8(KServerConfigString1, "encoding=\"UTF-8\"");
+ err = TheDb.Create(KTestDbName1, &KServerConfigString1);
+ TEST2(err, KErrNone);
+
+ err = TheDb.Exec(_L8("CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER, F2 BLOB)"));
+ TEST2(err, 1);
+
+ err = stmt.Prepare(TheDb, _L8("SELECT * FROM main GROUP BY GROUP BY main.Id"));
+ stmt.Close();
+ TEST(err != KErrNone && err != KErrServerTerminated);
+
+ TheDb.Close();
+ err = RSqlDatabase::Delete(KTestDbName1);
+ TEST2(err, KErrNone);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4007
+@SYMTestCaseDesc Test for DEF115331 - SQL, bad code coverage for db reindexing if default collation has changed.
+ The test does the following steps, using public shared and private secure database:
+ 1) Creates a test database with a table and one index using one of the collations.
+ 2) Updates the symbian_settings table, setting the collation dll name column value
+ to be a "bbbababz" string (Simulates that there is no valid collation dll name).
+ 3) Reopens the database. This operation should cause a database reindexing, since the index uses
+ one of the user-defined collation methods.
+ The default system collation dll name should be stored in the symbian_settings table.
+ 4) Verifies that symbian_settings table contains only one record and that the collation dll name
+ column value has been updated.
+@SYMTestPriority Medium
+@SYMTestActions Test for DEF115331 - SQL, bad code coverage for db reindexing if default collation has changed.
+@SYMTestExpectedResults Test must not fail
+@SYMDEF DEF115331
+*/
+void DEF115331L()
+ {
+ const TPtrC KDbNames[] = {KTestDbName1(), KTestDbName2()};
+
+ for(TInt i=0;i<(sizeof(KDbNames)/sizeof(KDbNames[0]));++i)
+ {
+ //Step 1: Create a test database with a table and one index using one of the collations.
+ (void)RSqlDatabase::Delete(KDbNames[i]);
+ TInt err = TheDb.Create(KDbNames[i]);
+ TEST2(err, KErrNone);
+
+ err = TheDb.Exec(_L("CREATE TABLE A(C TEXT)"));
+ TEST2(err, 1);
+
+ err = TheDb.Exec(_L("CREATE INDEX I ON A(C COLLATE CompareC1)"));
+ TEST2(err, 1);
+
+ //Step 2: Make sure that the collation dll name is set and unique (not the default collation).
+ err = TheDb.Exec(_L("UPDATE symbian_settings SET CollationDllName='bbbababz'"));
+ TEST2(err, 1);
+
+ TheDb.Close();
+
+ //Step 3: Reopen the database. That step should cause a database reindexing, because the default collation dll
+ // name is not the one stored in the table.
+ err = TheDb.Open(KDbNames[i]);
+ TEST2(err, KErrNone);
+
+ TSqlScalarFullSelectQuery query(TheDb);
+
+ //Step 4: Check that the settigns table has only one record.
+ TInt cnt = query.SelectIntL(_L("SELECT COUNT(*) FROM symbian_settings"));
+ TEST2(cnt, 1);
+
+ //Step 5: Check that the collation dll name in the settings table has been updated.
+ TFileName collationDllName;
+ err = query.SelectTextL(_L("SELECT CollationDllName FROM symbian_settings"), collationDllName);
+ TEST2(err, KErrNone);
+ _LIT(KTestCollationDllName, "bbbababz");//The same as the used in step 2 - above.
+ TEST(collationDllName != KTestCollationDllName);
+
+ TheDb.Close();
+ err = RSqlDatabase::Delete(KDbNames[i]);
+ TEST2(err, KErrNone);
+ }
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4079
+@SYMTestCaseDesc RSqlDatabase::Create() and RSqlDatabase::Open() - injection test
+ The test attempts to create or open a database which name contains
+ "DELETE FROM symbian_settings" statement.If it is possible to open or
+ create a database with that name, the "symbian_settings" table content
+ should stay unchanged.
+@SYMTestPriority Medium
+@SYMTestActions RSqlDatabase::Create() and RSqlDatabase::Open() - injection test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ5792
+*/
+void InjectionTest()
+ {
+ TInt err = TheDb.Create(KDbInjectedName1);
+ TEST(err != KErrNone);
+
+ err = TheDb.Create(KDbInjectedName2);
+ TEST2(err, KErrNone);
+
+ TSqlScalarFullSelectQuery query(TheDb);
+ TInt recCount = 0;
+ TRAP(err, recCount = query.SelectIntL(_L("SELECT COUNT(*) FROM symbian_settings")));
+ TEST2(err, KErrNone);
+ TEST2(recCount, 1);
+ TheDb.Close();
+
+ err = TheDb.Open(KDbInjectedName2);
+ TEST2(err, KErrNone);
+ recCount = 0;
+ query.SetDatabase(TheDb);
+ TRAP(err, recCount = query.SelectIntL(_L("SELECT COUNT(*) FROM symbian_settings")));
+ TEST2(err, KErrNone);
+ TEST2(recCount, 1);
+ TheDb.Close();
+
+ (void)RSqlDatabase::Delete(KDbInjectedName2);
+ (void)RSqlDatabase::Delete(KDbInjectedName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4038
+@SYMTestCaseDesc Background compaction - two connections usability test.
+ The test creates a database connection with a background compaction mode. The the test
+ locks the database in a transaction. Then the test creates a second connection
+ to the same database while the first connection is in a transaction.
+@SYMTestPriority Medium
+@SYMTestActions Background compaction - two connections usability test.
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ10271
+*/
+void TwoConnectionsTest()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ RSqlDatabase db1, db2;
+ TInt err = db1.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = db1.Exec(_L("CREATE TABLE A(I INTEGER); INSERT INTO A VALUES(1)"));
+ TEST2(err, 1);
+ err = db1.Exec(_L("BEGIN TRANSACTION"));
+ TEST(err >= 0);
+ err = db1.Exec(_L("INSERT INTO A VALUES(2)"));
+ TEST2(err, 1);
+ err = db2.Open(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = db1.Exec(_L("COMMIT TRANSACTION"));
+ TEST(err >= 0);
+ db2.Close();
+ db1.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+TInt StackOverflowThreadFunc(void* aData)
+ {
+ CTrapCleanup* tc = CTrapCleanup::New();
+ TEST(tc != NULL);
+
+ User::SetJustInTime(EFalse); // disable debugger panic handling
+
+ TInt* cntptr = reinterpret_cast<TInt*> (aData);
+ TEST(cntptr != NULL);
+ TInt cnt = *cntptr;
+
+ HBufC* buf = HBufC::New(cnt * 12 + 32);//enough for the "SELECT Id FROM A WHERE Id=v1 OR Id=v2 OR ..." string
+ if(!buf)
+ {
+ delete tc;
+ return KErrNoMemory;
+ }
+ TPtr sql = buf->Des();
+
+ TInt err = TheDb.Open(KTestDbName1);
+ if(err != KErrNone)
+ {
+ delete buf;
+ delete tc;
+ return err;
+ }
+
+ TTime now;
+ now.UniversalTime();
+ TInt64 seed = now.Int64();
+
+ sql.Copy(_L("SELECT Id FROM A WHERE "));
+ for(TInt i=0;i<cnt;++i)
+ {
+ sql.Append(_L("Id="));
+ sql.AppendNum(Math::Rand(seed) % cnt);
+ sql.Append(_L(" OR "));
+ }
+ sql.SetLength(sql.Length() - 4);//Remove the last " OR "
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, sql);
+ stmt.Close();
+
+ TheDb.Close();
+ delete buf;
+ delete tc;
+
+ return err;
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4080
+@SYMTestCaseDesc SQL server stack overflow test
+ The test creates a database and runs a thread. The thread opens the database
+ and attempts to execute a SELECT statement, which format is:
+ "SELECT Id FROM A WHERE Id=1 OR Id=2 OR...OR Id=N",
+ where N is a number passed as an argument from the main thread, starts from 100000
+ and is increased or decreased on each test iteration, depending on the reported result from the thread.
+ Finally, the main thread will report the max number of the OR subexpressions that can be included
+ in the SELECT statement, without an error to be reported.
+ The test should not crash the SQL server, if the server stack size and parsing tree depth has
+ been properly configured.
+@SYMTestPriority Medium
+@SYMTestActions SQL server stack overflow test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ5792
+*/
+void SqlServerStackOverflowTest()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER PRIMARY KEY AUTOINCREMENT)"));
+ TEST2(err, 1);
+ TheDb.Close();
+
+ TInt prev = 0, next = 100000;
+ while(Abs(next - prev) > 0)
+ {
+ TInt count = next;
+ TheTest.Printf(_L("'OR' expr. count: %d\r\n"), count);
+ RThread thread;
+ _LIT(KThreadName,"ORThread"); //stack minheap maxheap
+ err = thread.Create(KThreadName, &StackOverflowThreadFunc, 0x2000, 0x00100000, 0x02000000, &count);
+ TEST2(err, KErrNone);
+
+ TRequestStatus status;
+ thread.Logon(status);
+ TEST2(status.Int(), KRequestPending);
+ thread.Resume();
+ User::WaitForRequest(status);
+ User::SetJustInTime(ETrue); // enable debugger panic handling
+
+ TInt exitType = thread.ExitType();
+ const TDesC& exitCategory = thread.ExitCategory();
+ TInt exitReason = thread.ExitReason();
+ TheTest.Printf(_L("Exit type: %d, exit reason: %d, exit category: %S\r\n"), exitType, exitReason, &exitCategory);
+ thread.Close();
+ TEST(exitReason != KErrServerTerminated);
+ TEST(exitType != EExitPanic);
+
+ TInt tmp = next;
+ if(status.Int() != KErrNone)
+ {//The number of the OR subexpressions is too big and cannot be parsed. Decrease the number, repeat the test.
+ next -= Abs(next - prev) / 2;
+ }
+ else
+ {//KErrNone: The number of the OR subexpressions has been successfully parsed. Increase the number, repeat the test.
+ next += Abs(next - prev) / 2;
+ }
+ prev = tmp;
+ }
+ TheTest.Printf(_L("The test has succeeded with an expression with %d ORs\r\n"), prev);
+ }
+
+void AssertSettingsTable()
+ {
+ TSqlScalarFullSelectQuery query(TheDb);
+ TInt recCount = 0;
+ TRAPD(err, recCount = query.SelectIntL(_L("SELECT COUNT(*) FROM symbian_settings")));
+ TEST2(err, KErrNone);
+ TEST2(recCount, 1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4086
+@SYMTestCaseDesc RSqlBlobWriteStream::OpenL() and RSqlBlobReadStream::OpenL() - injection test
+ The test attempts to open a blob stream with an attached database name containing
+ "DELETE FROM symbian_settings" statement. The test should not delete the content of the
+ "symbian_settings" table.
+ The test also attempts to open a blob stream with a set of very long database/table/column names.
+@SYMTestPriority Medium
+@SYMTestActions RSqlBlobWriteStream::OpenL() and RSqlBlobReadStream::OpenL() - injection test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ5792
+ REQ10410
+ REQ10411
+ REQ10418
+*/
+void BlobStreamInjectionTest()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("INSERT INTO A VALUES(1, x'11223344556677889900')"));
+ TEST2(err, 1);
+ _LIT(KAttachDb, "AttachDb");
+ err = TheDb.Attach(KTestDbName1, KAttachDb);
+ TEST2(err, KErrNone);
+ //RSqlBlobWriteStream::OpenL() - attached database name injected
+ RSqlBlobWriteStream strm1;
+ TRAP(err, strm1.OpenL(TheDb, _L("A"), _L("Data"), 1, _L("Id;DELETE FROM symbian_settings;")));
+ TEST(err != KErrNone);
+ AssertSettingsTable();
+ //RSqlBlobReadStream::OpenL() - attached database name injected
+ RSqlBlobReadStream strm2;
+ TRAP(err, strm2.OpenL(TheDb, _L("A"), _L("Data"), 1, _L("Id;DELETE FROM symbian_settings;")));
+ TEST(err != KErrNone);
+ AssertSettingsTable();
+ //Attempt to open a write blob stream with a set of very long database/table/column names.
+ TBuf<KMaxFileName + 10> longName;
+ longName.SetLength(longName.MaxLength());
+ RSqlBlobWriteStream strm3;
+ TRAP(err, strm3.OpenL(TheDb, longName, longName, 1, longName));
+ TEST(err != KErrNone);
+ //Attempt to open a read blob stream with a set of very long database/table/column names.
+ RSqlBlobReadStream strm4;
+ TRAP(err, strm4.OpenL(TheDb, longName, longName, 1, longName));
+ TEST(err != KErrNone);
+ //Attempt to open a write blob stream with a set of KNullDesC database/table/column names.
+ RSqlBlobWriteStream strm5;
+ TRAP(err, strm5.OpenL(TheDb, KNullDesC, KNullDesC, 1, KNullDesC));
+ TEST(err != KErrNone);
+ //Attempt to open a read blob stream with a set of KNullDesC database/table/column names.
+ RSqlBlobReadStream strm6;
+ TRAP(err, strm6.OpenL(TheDb, KNullDesC, KNullDesC, 1, KNullDesC));
+ TEST(err != KErrNone);
+ //
+ err = TheDb.Detach(KAttachDb);
+ TEST2(err, KErrNone);
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4087
+@SYMTestCaseDesc Bound parameter values test.
+ The test verifies that bound parameters with big text/binary values retain their values after
+ the RSqlStatement::Reset() call. The old bound paramegter values can be used for the next
+ RSqlStatement::Exec() call.
+@SYMTestActions Bound parameter values test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority High
+@SYMREQ REQ5792
+*/
+void BoundParameterValuesTest()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+ err = TheDb.Exec(_L("CREATE TABLE A2(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt1, stmt2;
+ err = stmt1.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+ err = stmt2.Prepare(TheDb, _L("INSERT INTO A2 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+ //Insert 1 record into table "A1". T2 = "ZZZZ.....".
+ TheBuf.SetLength(KBufLen - 100);
+ TheBuf.Fill(TChar('Z'));
+ err = stmt1.BindText(0, TheBuf);
+ TEST2(err, KErrNone);
+ err = stmt1.BindText(1, TheBuf);
+ TEST2(err, KErrNone);
+ err = stmt1.Exec();
+ TEST2(err, 1);
+ err = stmt1.Reset();
+ TEST2(err, KErrNone);
+ //Insert 1 record into table "A2". T2 = "AAAAAAA.....".
+ TheBuf.SetLength(KBufLen);
+ TheBuf.Fill(TChar('A'));
+ err = stmt2.BindText(0, TheBuf);
+ TEST2(err, KErrNone);
+ err = stmt2.BindText(1, TheBuf);
+ TEST2(err, KErrNone);
+ err = stmt2.Exec();
+ TEST2(err, 1);
+ err = stmt2.Reset();
+ TEST2(err, KErrNone);
+ //Insert 1 record into table "A1". T2 not set. T2 should be initialized with the previous bound value - "ZZZZZZ....".
+ //If the problem is not fixed, the SQLITE will attempt to access an already deleted region of memory.
+ TheBuf.SetLength(KBufLen - 100);
+ TheBuf.Fill(TChar('B'));
+ err = stmt1.BindText(0, TheBuf);
+ TEST2(err, KErrNone);
+ err = stmt1.Exec();
+ TEST2(err, 1);
+ err = stmt1.Reset();
+ TEST2(err, KErrNone);
+
+ stmt2.Close();
+ stmt1.Close();
+
+ //Check the inserted records.
+ TSqlScalarFullSelectQuery q(TheDb);
+ TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=1"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST2(TheBuf.Length(), (KBufLen - 100));
+ for(TInt i1=0;i1<(KBufLen - 100);++i1)
+ {
+ TEST2(TheBuf[i1], TChar('Z'));
+ }
+ TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=2"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST2(TheBuf.Length(), (KBufLen - 100));
+ for(TInt i2=0;i2<(KBufLen - 100);++i2)
+ {
+ TEST2(TheBuf[i2], TChar('Z'));
+ }
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4076
+@SYMTestCaseDesc Bound parameter values test.
+ The test verifies that when a RSqlParamWriteStream object is used for binding parameter values,
+ it is safe to erverse the order of RSqlParamWriteStream::Close() and RSqlStatement::Close() calls.
+@SYMTestActions Bound parameter values test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority High
+@SYMREQ REQ5792
+*/
+void BoundParameterValuesTest2()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+ RSqlParamWriteStream strm;
+ err = strm.BindText(stmt, 0);
+ TEST2(err, KErrNone);
+ err = stmt.Exec();
+ TEST2(err, 1);
+ stmt.Close();
+ strm.Close();
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4077
+@SYMTestCaseDesc Bound parameter values test.
+ The test verifies that when a RSqlParamWriteStream object is used for binding parameter values,
+ it is possible to write the parameter value, then call RSqlParamWriteStream::Close() and finally -
+ RSqlStatement::Exec() to execute the operation (an INSERT statement). The test verifies that the record
+ has really been inserted and the column value is equal to the bound parameter value
+@SYMTestActions Bound parameter values test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority High
+@SYMREQ REQ5792
+*/
+void BoundParameterValuesTest3()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+ RSqlParamWriteStream strm;
+ err = strm.BindText(stmt, 0);
+ TEST2(err, KErrNone);
+ _LIT(KText, "AAAA");
+ TRAP(err, strm.WriteL(KText));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ strm.Close();
+ err = stmt.Exec();
+ TEST2(err, 1);
+ stmt.Close();
+
+ TSqlScalarFullSelectQuery q(TheDb);
+ TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText() == TheBuf);
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4083
+@SYMTestCaseDesc Bound parameter values test.
+ The test prepares an INSERT sql statement and inserts two records using streams to bind the parameter values.
+ For the second INSERT no parameter value is bound to the first parameter. The expectation is that the value
+ that has been bound for the first record will be used for the second record also.
+@SYMTestActions Bound parameter values test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority High
+@SYMREQ REQ5792
+*/
+void BoundParameterValuesTest4()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+
+ RSqlParamWriteStream strm;
+ err = strm.BindText(stmt, 0);
+ TEST2(err, KErrNone);
+ _LIT(KText1, "AAAA");
+ TRAP(err, strm.WriteL(KText1));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ strm.Close();
+
+ err = strm.BindText(stmt, 1);
+ TEST2(err, KErrNone);
+ _LIT(KText2, "BBBBBBBBBB");
+ TRAP(err, strm.WriteL(KText2));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ strm.Close();
+
+ err = stmt.Exec();
+ TEST2(err, 1);
+ err = stmt.Reset();
+ TEST2(err, KErrNone);
+
+ err = strm.BindText(stmt, 1);
+ TEST2(err, KErrNone);
+ _LIT(KText3, "CCCCCCCCCCC");
+ TRAP(err, strm.WriteL(KText3));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ strm.Close();
+
+ err = stmt.Exec();
+ TEST2(err, 1);
+
+ stmt.Close();
+
+ TSqlScalarFullSelectQuery q(TheDb);
+ TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=1"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText1() == TheBuf);
+ TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=1"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText2() == TheBuf);
+
+ TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=2"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText1() == TheBuf);
+ TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=2"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText3() == TheBuf);
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4105
+@SYMTestCaseDesc Bound parameter values test.
+ BC test. Even though it is correct to execute only one CommitL() on a parameter stream,
+ it should be possible to execute more than one CommitL(). It should be possible also
+ the stream data to be updated after the first commit operation and the expectation is that
+ the updated parameter data should be used for the column value.
+@SYMTestActions Bound parameter values test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority High
+@SYMREQ REQ5792
+*/
+void BoundParameterValuesTest5()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)"));
+ TEST2(err, 1);
+
+ RSqlStatement stmt;
+ err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)"));
+ TEST2(err, KErrNone);
+
+ RSqlParamWriteStream strm;
+ err = strm.BindText(stmt, 0);
+ TEST2(err, KErrNone);
+ _LIT(KText1, "AAAA");
+ TRAP(err, strm.WriteL(KText1));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ TRAP(err, strm.Sink()->SeekL(MStreamBuf::EWrite, EStreamBeginning, 0));
+ TEST2(err, KErrNone);
+ _LIT(KText2, "DTAA");
+ TRAP(err, strm.WriteL(KText2));
+ TEST2(err, KErrNone);
+ TRAP(err, strm.CommitL());
+ TEST2(err, KErrNone);
+ strm.Close();
+
+ err = stmt.Exec();
+ TEST2(err, 1);
+
+ stmt.Close();
+
+ TSqlScalarFullSelectQuery q(TheDb);
+ TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=1"), TheBuf));
+ TEST2(err, KErrNone);
+ TEST(KText2() == TheBuf);
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+void PrintConfig(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<128> config;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterConfig, config) == KErrNone)
+ {
+ _LIT(KCacheSize, "Cache size: %S pages\r\n");
+ _LIT(KPageSize, "Page size: %S bytes\r\n");
+ _LIT(KEncoding, "Encoding: %S\r\n");
+ _LIT(KDefaultSoftHeapLimit, "Default soft heap limit: %S Kb\r\n");
+ _LIT(KVacuumMode, "Vacuum mode: %S\r\n");
+
+ TPtrC KText[] = {KCacheSize(), KPageSize(), KEncoding(), KDefaultSoftHeapLimit(), KVacuumMode()};
+
+ for(TInt i=0;i<config.Length();++i)
+ {
+ if(config[i] == TChar(';'))
+ {
+ config[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(config);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+void PrintFileIo(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<300> countersValues;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterFileIO, countersValues) == KErrNone)
+ {
+ TheTest.Printf(_L("=========================\r\n"));
+ _LIT(KFileCreate, "File Create");
+ _LIT(KFileOpen, "File Open");
+ _LIT(KFileClose, "File Close");
+ _LIT(KFileDelete, "File Delete");
+ _LIT(KFileRead, "File Read");
+ _LIT(KFileWrite, "File Write");
+ _LIT(KFileSeek, "File Seek");
+ _LIT(KFileSize, "File Size");
+ _LIT(KFileSetSize, "File SetSize");
+ _LIT(KFileSync, "File Sync");
+ _LIT(KFileDrive, "File Drive");
+ _LIT(KFileAdopt, "File Adopt");
+ _LIT(KFsClose, "Fs Close");
+ _LIT(KFsConnect, "Fs Connect");
+ _LIT(KFsGetSystemDrive, "Fs GetSystemDrive");
+ _LIT(KFsCreatePrivatePath, "Fs CreatePrivatePath");
+ _LIT(KFsPrivatePath, "Fs PrivatePath");
+ _LIT(KFsVolumeIoParam, "Fs VolumeIoParam");
+ _LIT(KFsEntry, "Fs Entry");
+ _LIT(KFsAtt, "Fs Att");
+ _LIT(KFileCreateTemp, "File CreateTemp");
+ _LIT(KFileAttach, "File Attach");
+ _LIT(KBytesWritten, "File Bytes Written");
+ _LIT(KBytesRead, "File Bytes Read");
+ TPtrC KText[] =
+ {
+ KFileCreate(), KFileOpen(), KFileClose(), KFileDelete(), KFileRead(), KFileWrite(), KFileSeek(), KFileSize(),
+ KFileSetSize(), KFileSync(), KFileDrive(), KFileAdopt(), KFsClose(), KFsConnect(), KFsGetSystemDrive(),
+ KFsCreatePrivatePath(), KFsPrivatePath(), KFsVolumeIoParam(), KFsEntry(), KFsAtt(), KFileCreateTemp(),
+ KFileAttach(), KBytesWritten(), KBytesRead()
+ };
+
+ for(TInt i=0;i<countersValues.Length();++i)
+ {
+ if(countersValues[i] == TChar(';'))
+ {
+ countersValues[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(countersValues);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+void PrintOsCall(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<300> countersValues;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterOsCall, countersValues) == KErrNone)
+ {
+ TheTest.Printf(_L("=========================\r\n"));
+ _LIT(KEOsFileClose, "FileClose");
+ _LIT(KEOsFileRead, "FileRead");
+ _LIT(KEOsFileWrite, "FileWrite");
+ _LIT(KEOsFileTruncate, "FileTruncate");
+ _LIT(KEOsFileSync, "FileSync");
+ _LIT(KEOsFileFileSize, "FileSize");
+ _LIT(KEOsFileLock, "FileLock");
+ _LIT(KEOsFileUnlock, "FileUnlock");
+ _LIT(KEOsFileCheckReservedLock, "FileCheckReservedLock");
+ _LIT(KEOsFileFileControl, "FileIoControl");
+ _LIT(KEOsFileSectorSize, "FileSectorSize");
+ _LIT(KEOsFileDeviceCharacteristics, "FileDeviceCharacteristics");
+ _LIT(KEOsVfsOpen, "VfsOpen");
+ _LIT(KEOsVfsDelete, "VfsDelete");
+ _LIT(KEOsVfsAccess, "VfsAccess");
+ _LIT(KEOsVfsFullPathName, "VfsFullPathName");
+ _LIT(KEOsVfsRandomness, "VfsRandomnes");
+ _LIT(KEOsVfsSleep, "VfsSleep");
+ _LIT(KEOsVfsCurrentTime, "VfsCurrentTime");
+ _LIT(KEOsVfsGetLastError, "VfsGetLastError");
+ TPtrC KText[] =
+ {
+ KEOsFileClose(), KEOsFileRead(), KEOsFileWrite(), KEOsFileTruncate(), KEOsFileSync(),
+ KEOsFileFileSize(), KEOsFileLock(), KEOsFileUnlock(), KEOsFileCheckReservedLock(), KEOsFileFileControl(),
+ KEOsFileSectorSize(), KEOsFileDeviceCharacteristics(),
+ KEOsVfsOpen(), KEOsVfsDelete(), KEOsVfsAccess(), KEOsVfsFullPathName(), KEOsVfsRandomness(), KEOsVfsSleep(),
+ KEOsVfsCurrentTime(), KEOsVfsGetLastError()};
+
+ for(TInt i=0;i<countersValues.Length();++i)
+ {
+ if(countersValues[i] == TChar(';'))
+ {
+ countersValues[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(countersValues);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+void PrintOsCallTime(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<300> callTimes;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterOsCallTime, callTimes) == KErrNone)
+ {
+ TheTest.Printf(_L("=========================\r\n"));
+ _LIT(KEOsFileClose, "FileClose");
+ _LIT(KEOsFileRead, "FileRead");
+ _LIT(KEOsFileWrite, "FileWrite");
+ _LIT(KEOsFileTruncate, "FileTruncate");
+ _LIT(KEOsFileSync, "FileSync");
+ _LIT(KEOsFileFileSize, "FileSize");
+ _LIT(KEOsFileLock, "FileLock");
+ _LIT(KEOsFileUnlock, "FileUnlock");
+ _LIT(KEOsFileCheckReservedLock, "FileCheckReservedLock");
+ _LIT(KEOsFileFileControl, "FileIoControl");
+ _LIT(KEOsFileSectorSize, "FileSectorSize");
+ _LIT(KEOsFileDeviceCharacteristics, "FileDeviceCharacteristics");
+ _LIT(KEOsVfsOpen, "VfsOpen");
+ _LIT(KEOsVfsDelete, "VfsDelete");
+ _LIT(KEOsVfsAccess, "VfsAccess");
+ _LIT(KEOsVfsFullPathName, "VfsFullPathName");
+ _LIT(KEOsVfsRandomness, "VfsRandomnes");
+ _LIT(KEOsVfsSleep, "VfsSleep");
+ _LIT(KEOsVfsCurrentTime, "VfsCurrentTime");
+ _LIT(KEOsVfsGetLastError, "VfsGetLastError");
+ TPtrC KText[] =
+ {
+ KEOsFileClose(), KEOsFileRead(), KEOsFileWrite(), KEOsFileTruncate(), KEOsFileSync(),
+ KEOsFileFileSize(), KEOsFileLock(), KEOsFileUnlock(), KEOsFileCheckReservedLock(), KEOsFileFileControl(),
+ KEOsFileSectorSize(), KEOsFileDeviceCharacteristics(),
+ KEOsVfsOpen(), KEOsVfsDelete(), KEOsVfsAccess(), KEOsVfsFullPathName(), KEOsVfsRandomness(), KEOsVfsSleep(),
+ KEOsVfsCurrentTime(), KEOsVfsGetLastError()};
+
+ for(TInt i=0;i<callTimes.Length();++i)
+ {
+ if(callTimes[i] == TChar(';'))
+ {
+ callTimes[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(callTimes);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(_L("==Operation %S, time %S us\r\n"), &KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+void PrintIpc(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<300> countersValues;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterIpc, countersValues) == KErrNone)
+ {
+ TheTest.Printf(_L("=========================\r\n"));
+ _LIT(KIpcRq, "IPC requests");
+ _LIT(KIpcRead, "IPC read");
+ _LIT(KIpcWrite, "IPC write");
+ _LIT(KIpcReadBytes, "IPC read bytes");
+ _LIT(KIpcWriteBytes, "IPC write bytes");
+ TPtrC KText[] =
+ {
+ KIpcRq(), KIpcRead(), KIpcWrite(), KIpcReadBytes(), KIpcWriteBytes()
+ };
+
+ for(TInt i=0;i<countersValues.Length();++i)
+ {
+ if(countersValues[i] == TChar(';'))
+ {
+ countersValues[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(countersValues);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+void PrintMemory(TSqlResourceProfiler& aProfiler)
+ {
+ TBuf8<300> countersValues;
+ if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterMemory, countersValues) == KErrNone)
+ {
+ TheTest.Printf(_L("=========================\r\n"));
+ _LIT(KMemorySrvAllocatedCnt, "Server allocated cnt");
+ _LIT(KMemorySrvAllocatedSize, "Server allocated size");
+ _LIT(KMemorySrvFreeSpace, "Server free space");
+ _LIT(KMemorySrvLargestBlockSize, "Server larges block size");
+ _LIT(KMemorySQLiteAllocatedCnt, "SQLite allocated cnt");
+ _LIT(KMemorySQLiteReallocatedCnt, "SQLite reallocated cnt");
+ _LIT(KMemorySQLiteFreedCnt, "SQLite freed cnt");
+ _LIT(KMemorySQLiteAllocatedBytes, "SQLite allocated bytes");
+ _LIT(KMemorySQLiteFreedBytes, "SQLite freed bytes");
+ _LIT(KMemorySQLiteAllocTime, "SQLite alloc, us");
+ _LIT(KMemorySQLiteReallocTime, "SQLite realloc, us");
+ _LIT(KMemorySQLiteFreeTime, "SQLite free, us");
+ TPtrC KText[] =
+ {
+ KMemorySrvAllocatedCnt(), KMemorySrvAllocatedSize(), KMemorySrvFreeSpace(), KMemorySrvLargestBlockSize(),
+ KMemorySQLiteAllocatedCnt(), KMemorySQLiteReallocatedCnt(), KMemorySQLiteFreedCnt(),
+ KMemorySQLiteAllocatedBytes(), KMemorySQLiteFreedBytes(),
+ KMemorySQLiteAllocTime(), KMemorySQLiteReallocTime(), KMemorySQLiteFreeTime()
+ };
+
+ for(TInt i=0;i<countersValues.Length();++i)
+ {
+ if(countersValues[i] == TChar(';'))
+ {
+ countersValues[i] = TChar(' ');
+ }
+ }
+ TInt idx = 0;
+ TLex8 lex(countersValues);
+ while (!lex.Eos() && idx < (sizeof(KText)/sizeof(KText[0])))
+ {
+ TPtrC8 num8 = lex.NextToken();
+ TBuf<20> num;
+ num.Copy(num8);
+ TheTest.Printf(_L("==%S=%S\r\n"), &KText[idx], &num);
+ ++idx;
+ }
+ }
+ }
+
+/**
+@SYMTestCaseID SYSLIB-SQL-UT-4088
+@SYMTestCaseDesc TSqlResouceProfiler - file I/O and configuration test.
+ The test enables the file I/O profiling and then executes a simple INSERT statement
+ and prints out the profiling results. The test also prints the current database configuration.
+@SYMTestActions TSqlResouceProfiler - file I/O and configuration test.
+@SYMTestExpectedResults Test must not fail
+@SYMTestPriority Medium
+@SYMREQ REQ5792
+*/
+void ProfilerTest()
+ {
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ TInt err = TheDb.Create(KTestDbName1);
+ TEST2(err, KErrNone);
+ err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER, T TEXT)"));
+ TEST2(err, 1);
+
+ TSqlResourceProfiler profiler(TheDb);
+
+ PrintConfig(profiler);
+
+ (void)profiler.Start(TSqlResourceProfiler::ESqlCounterFileIO);
+ (void)profiler.Start(TSqlResourceProfiler::ESqlCounterOsCall);
+ (void)profiler.Start(TSqlResourceProfiler::ESqlCounterOsCallTime);
+ (void)profiler.Start(TSqlResourceProfiler::ESqlCounterIpc);
+ (void)profiler.Start(TSqlResourceProfiler::ESqlCounterMemory);
+
+ (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterFileIO);
+ (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterOsCall);
+ (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterOsCallTime);
+ (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterIpc);
+ (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterMemory);
+
+ err = TheDb.Exec(_L("INSERT INTO A VALUES(1, 'ABCDEEFGH')"));
+ TEST2(err, 1);
+
+ PrintFileIo(profiler);
+ PrintOsCall(profiler);
+ PrintOsCallTime(profiler);
+ PrintIpc(profiler);
+ PrintMemory(profiler);
+
+ (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterIpc);
+ (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterOsCallTime);
+ (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterOsCall);
+ (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterFileIO);
+ (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterMemory);
+
+ TheDb.Close();
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ }
+
+TInt CompoundSelectStackOverflowThreadFunc(void* aData)
+ {
+ CTrapCleanup* tc = CTrapCleanup::New();
+ TEST(tc != NULL);
+
+ User::SetJustInTime(EFalse); // disable debugger panic handling
+
+ TInt* cntptr = reinterpret_cast<TInt*> (aData);
+ TEST(cntptr != NULL);
+ const TInt KSelectStmtCnt = *cntptr;
+
+ HBufC* buf = HBufC::New(KSelectStmtCnt * 25 + 32);//enough for the "SELECT I FROM A UNION SELECT I FROM A..." string
+ if(!buf)
+ {
+ delete tc;
+ return KErrNoMemory;
+ }
+ TPtr sql = buf->Des();
+
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ RSqlDatabase db;
+ TInt err = db.Create(KTestDbName1);
+ if(err != KErrNone)
+ {
+ delete buf;
+ return err;
+ }
+ err = db.Exec(_L("CREATE TABLE A(I INTEGER);INSERT INTO A VALUES(1);"));
+ if(err < 1)
+ {
+ delete buf;
+ return err;
+ }
+
+ for(TInt i=0;i<KSelectStmtCnt;i++)
+ {
+ sql.Append(_L("SELECT I FROM A UNION "));
+ }
+ sql.SetLength(sql.Length() - 7);
+ RSqlStatement stmt;
+ err = stmt.Prepare(db, sql);//This call can crash the server with "stack overflow"
+ stmt.Close();
+
+ db.Close();
+ delete buf;
+ (void)RSqlDatabase::Delete(KTestDbName1);
+ return err;
+ }
+
+void CompoundSelectStackOverflowTest()
+ {
+ const TInt KMaxSelectStmtCnt = 64;
+ for(TInt cnt=KMaxSelectStmtCnt;cnt>0;--cnt)
+ {
+ TheTest.Printf(_L("SELECT statement count: %d\r\n"), cnt);
+ RThread thread;
+ _LIT(KThreadName,"S2Thread"); //stack minheap maxheap
+ TInt err = thread.Create(KThreadName, &CompoundSelectStackOverflowThreadFunc, 0x2000, 0x00100000, 0x02000000, &cnt);
+ TEST2(err, KErrNone);
+
+ TRequestStatus status;
+ thread.Logon(status);
+ TEST2(status.Int(), KRequestPending);
+ thread.Resume();
+ User::WaitForRequest(status);
+ User::SetJustInTime(ETrue); // enable debugger panic handling
+
+ TInt exitType = thread.ExitType();
+ const TDesC& exitCategory = thread.ExitCategory();
+ TInt exitReason = thread.ExitReason();
+ TheTest.Printf(_L("Exit type: %d, exit reason: %d, exit category: %S\r\n"), exitType, exitReason, &exitCategory);
+ thread.Close();
+ if(exitReason == KErrServerTerminated) //SQL server --> stack overflow
+ {
+ continue;
+ }
+ TEST2(exitReason, KErrNone);
+ TheTest.Printf(_L(" The test has succeeded with SELECT statement count=%d\r\n"), cnt);
+ break;
+ }
+ }
+
+void DoTestsL()
+ {
+ TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3512 RSqlStatement::ColumnCount() tests "));
+ ColumnCountTest();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3513 RSqlStatement::ColumnCount(), non-SELECT tests "));
+ ColumnCountTest2();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3514 RSqlStatement::DeclaredColumnType() tests "));
+ DeclaredColumnTypeTest();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4017 RSqlStatement::ColumnName() tests"));
+ ColumnNameTest();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4018 RSqlStatement::ParameterName() and RSqlStatement::ParamName() tests"));
+ ParamNameTest();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4006 DEF115300 - SqlSrv.EXE::!SQL Server when preparing invalid LEFT JOIN sql query "));
+ DEF115300();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4007 DEF115331 - SQL, bad code coverage for db reindexing if default collation has changed "));
+ DEF115331L();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4079 RSqlDatabase::Create() and RSqlDatabase::Open() - injection tests"));
+ InjectionTest();
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4038 Two connections test"));
+ TwoConnectionsTest();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4080 SQL server stack overflow test"));
+ SqlServerStackOverflowTest();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4086 RSqlBlobWriteStream/RSqlBlobReadStream injection test"));
+ BlobStreamInjectionTest();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4087 Bound parameter values test 1"));
+ BoundParameterValuesTest();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4076 Bound parameter values test 2"));
+ BoundParameterValuesTest2();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4077 Bound parameter values test 3"));
+ BoundParameterValuesTest3();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4083 Bound parameter values test 4"));
+ BoundParameterValuesTest4();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4105 Bound parameter values test 5"));
+ BoundParameterValuesTest5();
+ TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4088 TSqlResourceProfiler - file I/O and configuration test"));
+ ProfilerTest();
+ TheTest.Next( _L(" Compound SELECT, stack overflow test"));
+ CompoundSelectStackOverflowTest();
+ }
+
+TInt E32Main()
+ {
+ TheTest.Title();
+
+ CTrapCleanup* tc = CTrapCleanup::New();
+
+ __UHEAP_MARK;
+
+ CreateTestEnv();
+ DeleteTestFiles();
+ TRAPD(err, DoTestsL());
+ DeleteTestFiles();
+ TEST2(err, KErrNone);
+
+ __UHEAP_MARKEND;
+
+ TheTest.End();
+ TheTest.Close();
+
+ delete tc;
+
+ User::Heap().Check();
+ return KErrNone;
+ }