--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/tdbms/t_dbdefect.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1333 @@
+// Copyright (c) 2004-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 <d32dbms.h>
+#include <e32math.h>
+#include <e32test.h>
+#include <f32file.h>
+#include <s32buf.h>
+
+LOCAL_D RTest TheTest (_L ("t_dbdefect"));
+LOCAL_D CTrapCleanup* TheTrapCleanup = NULL;
+LOCAL_D RSemaphore TheWaitToStartSem;
+LOCAL_D RSemaphore TheWaitForThreadsReadySem;
+LOCAL_D RFs TheFs;
+LOCAL_D RDbs TheDbs1, TheDbs2;
+LOCAL_D RDbNamedDatabase TheDb1, TheDb2;
+
+_LIT (KName, "ConnectTestThread_");
+_LIT (KStart, "Starting thread %x.\n");
+_LIT (KConnect, "Thread %x: Waiting to connect...\n");
+_LIT (KConSuccess, "Thread %x: Connection succeeded.\n");
+_LIT (KConFailed, "Thread %x: Connection failed. Error %d.\n");
+_LIT (KStatus, "Status of thread %x is %d.\n");
+
+
+_LIT(KTable, "TABLE");
+_LIT(KColName, "Fld");
+_LIT(KCol2Name, "Fld2");
+_LIT(KDbName, "C:\\DBMS-TST\\TESTDB22.DB");
+_LIT(KSQLInsert1, "INSERT INTO TABLE (Fld, Fld2) VALUES ('ACDC\\','BLAH')");
+_LIT(KSQLInsert2, "INSERT INTO TABLE (Fld) VALUES ('ABCDEFGH')");
+_LIT(KSQLInsert3, "INSERT INTO TABLE (Fld) VALUES ('A?CDEFGH')");
+_LIT(KSQLInsert4, "INSERT INTO TABLE (Fld) VALUES ('A?*?CDEFGH')");
+_LIT(KSQLInsert5, "INSERT INTO TABLE (Fld) VALUES ('A*CDEFGH')");
+_LIT(KSQLInsert6, "INSERT INTO TABLE (Fld, Fld2) VALUES ('ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP','ADCB')");
+_LIT(KSQLInsert7, "INSERT INTO TABLE (Fld) VALUES ('XZD\\FZX')");
+
+_LIT(KSqlRequestGranularity, "SELECT Fld FROM test WHERE (Fld LIKE '1' AND Fld LIKE '2') AND Fld LIKE '3' AND Fld LIKE '4' AND Fld LIKE '5' AND Fld LIKE '6'");
+
+_LIT(KText16Name, "text16");
+_LIT(KTableName, "test");
+_LIT(KIndexName, "test_index");
+_LIT(KMaxStringFormat, "%0256d");
+
+void TestCleanup()
+ {
+ TheDb2.Close();
+ TheDb1.Close();
+ TheDbs2.Close();
+ TheDbs1.Close();
+ (void)TheFs.Delete(KDbName);
+ TheFs.Close();
+ }
+
+//-----------------------------------------------------------------------------
+//
+// Test macros and functions.
+//
+//-----------------------------------------------------------------------------
+// If (!aValue) then the test will be panicked, the test data files will be
+// deleted.
+LOCAL_C void Check(TInt aValue, TInt aLine)
+ {
+ if(!aValue)
+ {
+ TestCleanup();
+ TheTest(EFalse, aLine);
+ }
+ }
+
+
+// If (aValue != aExpected) then the test will be panicked, the test data files
+// will be deleted.
+LOCAL_C void Check(TInt aValue, TInt aExpected, TInt aLine)
+ {
+ if(aValue != aExpected)
+ {
+ RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
+ TestCleanup();
+ TheTest(EFalse, aLine);
+ }
+ }
+
+
+//Use these to test conditions.
+#define TEST(arg) ::Check((arg), __LINE__)
+#define TEST2(aValue, aExpected) ::Check((aValue), (aExpected), __LINE__)
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+struct TTest
+ {
+ const TText* result;
+ const TText* query;
+ };
+
+const TTest KQuery[]=
+ {
+ {_S("ACDC\\"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE 'ACDC\\' AND Fld2 LIKE '*BL*'")},
+ {_S("A*CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\*C*' ESCAPE '\\'")},
+ {_S("A?CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\?C*' ESCAPE '\\'")},
+ {_S("A?*?CDEFGH"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\?\\*\\?C*' ESCAPE '\\'")},
+ {_S("ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*1234*'")},
+ {_S("BLAH"),_S("SELECT Fld2 FROM TABLE WHERE Fld LIKE '*AC*' AND Fld2 LIKE '?LA?'")},
+ {_S("BLAH"),_S("SELECT Fld2 FROM TABLE WHERE Fld LIKE 'NOTINTABLE' OR Fld2 LIKE '?LA?'")},
+ {_S("ADCDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOPQRSTUVWXYZ123456789ACDEFGHIJKLMNOP"),_S("SELECT * FROM TABLE WHERE Fld LIKE '*ADC*' AND Fld2 LIKE 'ADC?'")},
+ {_S("A*CDEFGH"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE '*\\*C*' ESCAPE '\\'")},
+ {_S("XZD\\FZX"),_S("SELECT Fld FROM TABLE WHERE Fld LIKE '*D\\\\*' ESCAPE '\\'")}
+ };
+
+const TTest KBadQuery[]=
+ {
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'A?C' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'A*C' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '?A\\?C' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '?A\\?C?' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A\\??\\?C*' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*A*\\*C*' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'ABC' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE 'ABC*' ESCAPE '\\'")},
+ {_S(""),_S("SELECT * FROM TABLE WHERE Fld LIKE '*ABC' ESCAPE '\\'")}
+ };
+
+const TInt KNumQueries = 10;
+const TInt KNumBadQueries = 9;
+const TInt KThreadCount = 3;
+const TInt KOneSecond = 1000000;
+const TInt KDbNameLen = 255;
+const TInt KMaxColName = 32;
+
+static void DoDbmsConnectThreadSubFunctionL (TInt aThreadNumber)
+ {
+ // The session
+ RDbs TheDbSession;
+ CleanupClosePushL (TheDbSession);
+
+ RDebug::Print (KStart (), aThreadNumber);
+ RDebug::Print (KConnect (), aThreadNumber);
+
+ // Signal the main thread to continue
+ TheWaitForThreadsReadySem.Signal (1);
+
+ // Wait until we are signalled
+ TheWaitToStartSem.Wait ();
+
+ // Connect to Dbms
+ TInt r = TheDbSession.Connect ();
+
+ if (r == KErrNone)
+ {
+ RDebug::Print (KConSuccess (), aThreadNumber);
+ TheDbSession.Close ();
+ }
+ else
+ {
+ RDebug::Print (KConFailed (), aThreadNumber, r);
+ User::Leave (r);
+ }
+
+ CleanupStack::PopAndDestroy (1); // session
+ }
+
+static TInt DoDbmsConnectThread (TAny* aThreadNumber)
+ {
+ __UHEAP_MARK;
+
+ CTrapCleanup* trapCleanup = CTrapCleanup::New ();
+ __ASSERT_ALWAYS (trapCleanup!=NULL, User::Invariant ());
+
+ TInt* threadNumber = static_cast <TInt*> (aThreadNumber);
+ TRAPD (err, DoDbmsConnectThreadSubFunctionL (*threadNumber));
+
+ delete trapCleanup;
+
+ __UHEAP_MARKEND;
+
+ return err;
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-CT-0644
+@SYMTestCaseDesc Test for defect no 44697
+@SYMTestPriority Medium
+@SYMTestActions Test for defect fixes
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ0000
+*/
+LOCAL_C void Defect_DEF44697L ()
+ {
+ TheTest.Next (_L (" @SYMTestCaseID:SYSLIB-DBMS-CT-0644 Defect_DEF44697L "));
+
+ __UHEAP_MARK;
+
+ // find out the number of open handles
+ TInt startProcessHandleCount;
+ TInt startThreadHandleCount;
+ RThread ().HandleCount (startProcessHandleCount, startThreadHandleCount);
+
+ /////////////////////
+ // The Test Begins...
+
+ // Create semaphores
+ ::CleanupClosePushL (::TheWaitForThreadsReadySem);
+ User::LeaveIfError (::TheWaitForThreadsReadySem.CreateLocal (0));
+
+ ::CleanupClosePushL (::TheWaitToStartSem);
+ User::LeaveIfError (::TheWaitToStartSem.CreateLocal (0));
+
+ // Create the threads.
+ RThread createTestThread_1;
+ RThread createTestThread_2;
+ RThread createTestThread_3;
+
+ TBuf<100> thread_name;
+ TInt KThreadNumber1 = 1;
+ TInt KThreadNumber2 = 2;
+ TInt KThreadNumber3 = 3;
+
+ // Create the first test thread______________________________
+ thread_name = KName ();
+ thread_name.AppendNum (KThreadNumber1);
+
+ User::LeaveIfError (
+ createTestThread_1.Create (thread_name,
+ (TThreadFunction) DoDbmsConnectThread,
+ KDefaultStackSize,
+ KMinHeapSize,
+ KMinHeapSize,
+ &KThreadNumber1));
+
+ // Default priority of Main thread is EPriorityNormal
+ createTestThread_1.SetPriority(EPriorityMore);
+
+ TheTest.Printf (_L ("%S thread started\n"), &thread_name);
+
+ // Request notification when the thread dies.
+ TRequestStatus threadStatus_1;
+ createTestThread_1.Logon (threadStatus_1);
+
+ //___________________________________________________________
+
+ // Create the second test thread______________________________
+ thread_name = KName ();
+ thread_name.AppendNum (KThreadNumber2);
+
+ User::LeaveIfError (
+ createTestThread_2.Create (thread_name,
+ (TThreadFunction) DoDbmsConnectThread,
+ KDefaultStackSize,
+ KMinHeapSize,
+ KMinHeapSize,
+ &KThreadNumber2));
+
+ // Default priority of Main thread is EPriorityNormal
+ createTestThread_2.SetPriority(EPriorityMore);
+
+ TheTest.Printf (_L ("%S thread started\n"), &thread_name);
+
+ // Request notification when the tread dies.
+ TRequestStatus threadStatus_2;
+ createTestThread_2.Logon (threadStatus_2);
+
+ //___________________________________________________________
+
+ // Create the third test thread______________________________
+ thread_name = KName ();
+ thread_name.AppendNum (KThreadNumber3);
+
+ User::LeaveIfError (
+ createTestThread_3.Create (thread_name,
+ (TThreadFunction) DoDbmsConnectThread,
+ KDefaultStackSize,
+ KMinHeapSize,
+ KMinHeapSize,
+ &KThreadNumber3));
+
+ // Default priority of Main thread is EPriorityNormal
+ createTestThread_3.SetPriority(EPriorityMore);
+
+ TheTest.Printf (_L ("%S thread started\n"), &thread_name);
+
+ // Request notification when the tread dies.
+ TRequestStatus threadStatus_3;
+ createTestThread_3.Logon (threadStatus_3);
+
+ //___________________________________________________________
+
+ TheTest (threadStatus_1.Int () == KRequestPending);
+ TheTest (threadStatus_2.Int () == KRequestPending);
+ TheTest (threadStatus_3.Int () == KRequestPending);
+
+ // Make threads eligible for execution
+ createTestThread_1.Resume ();
+ createTestThread_2.Resume ();
+ createTestThread_3.Resume ();
+
+ // The way this works is that the main thread blocks until all
+ // the test threads are ready (semaphore 1) and then signals them
+ // (semaphore 2).
+ //
+ // 1: Main thread Waits for ALL test threads to become ready.
+ // 2: Main thread Signals ALL test threads to run.
+ //
+ // 1: Test thread Signals Main thread
+ // 2: Test thread Waits for Main thread
+ //
+ // There is still a slight race condition between the
+ // test thread signalling (semaphore 1) and then waiting
+ // (semaphore 2) which is why we use both higher priority test
+ // threads and a timer.
+ //
+ // The problems come with the way Time slicing works due to
+ // other threads of higher priority being run.
+ //
+ // Higher priority: Ensures the test thread runs before the
+ // the main thread.
+ //
+ // Timer: Safeguards when multiple core processors are being used.
+ //
+ // The Higher priority fixes the problem on single core processors
+ // and multiple cores processors (SMP) where each core can run a
+ // thread.
+ //
+ // It should also ensure that if the system is so busy that it
+ // affects the test thread execution, the test thread will still
+ // get to the Wait state before the Main thread can Signal.
+ //
+ // However, on multiple cores the Main thread may run at the same
+ // time as the test thread, so we need to make sure that when the
+ // test thread Signals it can acheive its Wait state before the
+ // Main thread Signals. For example, if the timer has elapsed on the
+ // Main thread and the sytem is busy, the test thread should still
+ // run before the Main thread due to it higher priority.
+ //
+ // We also have to think about things like priority inheritance
+ // where a thread that has a handle on a Mutex inherits the same
+ // priority as a thread Waiting on it. This shouldn't happen for
+ // Semaphores as there is no one handle, i.e. no critical section.
+ //
+ // This higher priority inheritance will take affect when a low
+ // priority thread that has a handle on the Mutex blocks because of
+ // another medium priority running thread. So in effect a high
+ // priority thread Waiting on this Mutex is also blocked.
+ //
+ // It is also worth noting that on EKA1 emulator, scheduling is
+ // performed by windows. On EKA2 emulator scheduling is performed
+ // by Symbian so that it is the same as hardware.
+
+ TheWaitForThreadsReadySem.Wait();
+ TheWaitForThreadsReadySem.Wait();
+ TheWaitForThreadsReadySem.Wait();
+
+ // Sleep for a while to allow threads to block on the semaphore
+ User::After (KOneSecond<<2); // 4 seconds
+
+ // Signal all the threads to continue
+ TheWaitToStartSem.Signal (KThreadCount);
+
+ // Wait for all threads to complete, don't care on the order.
+ User::WaitForRequest (threadStatus_1);
+ User::WaitForRequest (threadStatus_2);
+ User::WaitForRequest (threadStatus_3);
+
+ TheTest.Printf (KStatus, KThreadNumber1, threadStatus_1.Int ());
+ TheTest.Printf (KStatus, KThreadNumber2, threadStatus_2.Int ());
+ TheTest.Printf (KStatus, KThreadNumber3, threadStatus_3.Int ());
+
+ TheTest (threadStatus_1.Int () == KErrNone);
+ TheTest (threadStatus_2.Int () == KErrNone);
+ TheTest (threadStatus_3.Int () == KErrNone);
+
+ CleanupStack::PopAndDestroy (&::TheWaitToStartSem);
+ CleanupStack::PopAndDestroy (&::TheWaitForThreadsReadySem);
+
+ // The Test Ends...
+ /////////////////////
+
+ // check that no handles have leaked
+ TInt endProcessHandleCount;
+ TInt endThreadHandleCount;
+ RThread ().HandleCount (endProcessHandleCount, endThreadHandleCount);
+
+ TheTest (startThreadHandleCount == endThreadHandleCount);
+
+ __UHEAP_MARKEND;
+ }
+
+
+
+// Test for LIKE Predicate for EDbColLongText16
+LOCAL_C void LikePredicateDbColLongText16TestL()
+ {
+ TheTest.Next (_L ("LikePredicateDbColLongText16TestL"));
+ //Creating database
+
+ RFs fsSession;
+ User::LeaveIfError(fsSession.Connect());
+ CleanupClosePushL(fsSession);
+ RDbNamedDatabase database;
+ User::LeaveIfError(database.Replace(fsSession, KDbName));
+ CleanupClosePushL(database);
+
+ //Create table
+
+ CDbColSet* columns= CDbColSet::NewLC();
+
+ TDbCol name(KColName,EDbColLongText16,KDbNameLen);
+ name.iAttributes = TDbCol::ENotNull;
+
+ TDbCol name2(KCol2Name,EDbColLongText16,KDbNameLen);
+
+ columns->AddL(name);
+ columns->AddL(name2);
+ User::LeaveIfError (database.CreateTable (KTable, *columns));
+ CleanupStack::PopAndDestroy(); // columns
+
+ // Insert values into table
+ TInt error = database.Execute(KSQLInsert1);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert2);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert3);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert4);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert5);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert6);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert7);
+ TheTest(error>=0);
+
+
+ TheTest.Next(_L("Test for valid LIKE predicate queries"));
+
+
+ for(TInt i =0;i<KNumQueries;++i)
+ {
+ RDebug::Print(_L("Executing statement: %s \n"),(KQuery[i].query));
+ RDbView view;
+ view.Prepare(database, TDbQuery(TPtrC(KQuery[i].query), EDbCompareFolded), view.EReadOnly);
+ view.EvaluateAll();
+ view.FirstL();
+ typedef TBuf<256> TScriptLine;
+ TInt count =0;
+ while (view.AtRow())
+ {
+ view.GetL();
+ count++;
+ RDbColReadStream rd;
+ rd.OpenLC(view,1);
+ TScriptLine text;
+ rd.ReadL(text,view.ColLength(1));
+ CleanupStack::PopAndDestroy();
+ RDebug::Print(_L("Expected result: %s Actual Result: %S\n"),(KQuery[i].result),&text);
+ TInt err = text.Compare(TPtrC(KQuery[i].result));
+ TheTest(err ==0);
+ view.NextL();
+ }
+ view.Close();
+ }
+
+
+ // test for illegal statements, check they return KErrArgument
+ TheTest.Next(_L("Test that illegal queries return KErrArgument"));
+
+
+ for(TInt j =0;j<KNumBadQueries;++j)
+ {
+ RDebug::Print(_L("Executing illegal statement: %s \n"),(KBadQuery[j].query));
+ RDbView view;
+ TInt prepErr = view.Prepare(database, TDbQuery(TPtrC(KBadQuery[j].query), EDbCompareFolded), view.EReadOnly);
+ TheTest(prepErr==KErrArgument);
+ view.Close();
+ }
+
+ CleanupStack::PopAndDestroy(&database); // database
+ CleanupStack::PopAndDestroy(&fsSession); // fsSession
+ }
+
+
+
+ // for LIKE Predicate for EDbColLongText8
+LOCAL_C void LikePredicateDbColLongText8TestL()
+ {
+ TheTest.Next (_L ("LikePredicate DbColLongText8 TestL"));
+
+ //Creating database
+
+ RFs fsSession;
+ User::LeaveIfError(fsSession.Connect());
+ CleanupClosePushL(fsSession);
+ RDbNamedDatabase database;
+ User::LeaveIfError(database.Replace(fsSession, KDbName));
+ CleanupClosePushL(database);
+
+ //Create table
+
+ CDbColSet* columns= CDbColSet::NewLC();
+
+ TDbCol name(KColName,EDbColLongText8,KDbNameLen);
+ name.iAttributes = TDbCol::ENotNull;
+
+ TDbCol name2(KCol2Name,EDbColLongText8,KDbNameLen);
+
+ columns->AddL(name);
+ columns->AddL(name2);
+
+ User::LeaveIfError (database.CreateTable (KTable, *columns));
+ CleanupStack::PopAndDestroy(); // columns
+
+ // Insert values into the table
+ TInt error = database.Execute(KSQLInsert1);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert2);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert3);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert4);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert5);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert6);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert7);
+ TheTest(error>=0);
+
+ TheTest.Next(_L("Test for valid LIKE predicate queries"));
+
+
+ for(TInt i =0;i<KNumQueries;++i)
+ {
+ RDebug::Print(_L("Executing statement: %s \n"),(KQuery[i].query));
+ RDbView view;
+ TInt prepErr = view.Prepare(database, TDbQuery(TPtrC(KQuery[i].query), EDbCompareFolded), view.EReadOnly);
+ TheTest(prepErr>=0);
+ TInt evErr = view.EvaluateAll();
+ TheTest(evErr==0);
+ TBuf8<256> result;
+ TBuf8<256> colname;
+ result.Copy(TPtrC(KQuery[i].result));
+ view.FirstL();
+
+ while (view.AtRow())
+ {
+ view.GetL();
+ RDbColReadStream rd;
+ rd.OpenLC(view,1);
+ rd.ReadL(colname,view.ColLength(1));
+ CleanupStack::PopAndDestroy();
+ RDebug::Print(_L("Expected result: %S Actual Result: %S\n"),&result,&colname);
+ TInt err = colname.CompareF(result);
+ TheTest(err ==0);
+
+ view.NextL();
+ }
+
+ view.Close();
+ }
+
+ // test for illegal statements, check they return KErrArgument
+ TheTest.Next(_L("Test that illegal queries return KErrArgument"));
+
+
+
+ for(TInt j =0;j<KNumBadQueries;++j)
+ {
+ RDebug::Print(_L("Executing illegal statement: %s \n"),(KBadQuery[j].query));
+ RDbView view;
+ TInt prepErr = view.Prepare(database, TDbQuery(TPtrC(KBadQuery[j].query), EDbCompareFolded), view.EReadOnly);
+ TheTest(prepErr==KErrArgument);
+
+ view.Close();
+ }
+
+ CleanupStack::PopAndDestroy(&database); // database
+ CleanupStack::PopAndDestroy(&fsSession); // fsSession
+ }
+
+
+
+// Test for LIKE Predicate for EDbColText
+LOCAL_C void LikePredicateDbColTextTestL()
+ {
+ TheTest.Next (_L ("LikePredicate DbColText TestL"));
+ //Creating database
+
+ RFs fsSession;
+ User::LeaveIfError(fsSession.Connect());
+ CleanupClosePushL(fsSession);
+ RDbNamedDatabase database;
+ User::LeaveIfError(database.Replace(fsSession, KDbName));
+ CleanupClosePushL(database);
+
+ //Create table
+
+ CDbColSet* columns= CDbColSet::NewLC();
+
+ TDbCol name(KColName,EDbColText,KDbNameLen);
+ name.iAttributes = TDbCol::ENotNull;
+
+ TDbCol name2(KCol2Name,EDbColText,KDbNameLen);
+
+ columns->AddL(name);
+ columns->AddL(name2);
+
+ User::LeaveIfError (database.CreateTable (KTable, *columns));
+ CleanupStack::PopAndDestroy(); // columns
+
+ // Insert values into the table
+ TInt error = database.Execute(KSQLInsert1);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert2);
+ TheTest(error>=0);
+ error =database.Execute(KSQLInsert3);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert4);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert5);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert6);
+ TheTest(error>=0);
+ error = database.Execute(KSQLInsert7);
+ TheTest(error>=0);
+
+
+ TheTest.Next(_L("Test for valid LIKE predicate queries"));
+
+
+ for(TInt i =0;i<KNumQueries;++i)
+ {
+ RDebug::Print(_L("Executing statement: %s \n"),(KQuery[i].query));
+ RDbView view;
+ TInt prepErr = view.Prepare(database, TDbQuery(TPtrC(KQuery[i].query), EDbCompareFolded), view.EReadOnly);
+ if(TPtrC(KQuery[i].result).Length() == 0)
+ {
+ TheTest(prepErr != KErrNone);
+ continue;
+ }
+
+ view.EvaluateAll();
+ TBufC<256> colname;
+ TBufC<256> res;
+ view.FirstL();
+ while (view.AtRow())
+ {
+ view.GetL();
+ colname = view.ColDes(1);
+ res= KQuery[i].result;
+ RDebug::Print(_L("Expected result: %s Actual Result: %S\n"),(KQuery[i].result),&colname);
+ TInt err = colname.Compare(TPtrC(KQuery[i].result));
+ TheTest(err ==0);
+ view.NextL();
+ }
+ view.Close();
+ }
+
+ // test for illegal statements, check they return KErrArgument
+ TheTest.Next(_L("Test that illegal queries return KErrArgument"));
+
+ for(TInt j =0;j<KNumBadQueries;++j)
+ {
+ RDebug::Print(_L("Executing illegal statement: %s \n"),(KBadQuery[j].query));
+ RDbView view;
+ TInt prepErr = view.Prepare(database, TDbQuery(TPtrC(KBadQuery[j].query), EDbCompareFolded), view.EReadOnly);
+ TheTest(prepErr==KErrArgument);
+ view.Close();
+ }
+
+ CleanupStack::PopAndDestroy(&database); // database
+ CleanupStack::PopAndDestroy(&fsSession); // fsSession
+ }
+
+
+
+ /**
+@SYMTestCaseID SYSLIB-DBMS-UT-1592
+@SYMTestCaseDesc Testing limited-ESCAPE-clause
+@SYMTestPriority High
+@SYMTestActions Execute DBMS query with ESCAPE-clause
+@SYMTestExpectedResults The test should not fail.
+@SYMDEF INC076370
+*/
+LOCAL_C void Defect_INC076370L()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-1592 Defect INC076370 "));
+ LikePredicateDbColTextTestL(); //EDbColText
+ LikePredicateDbColLongText16TestL(); //EDbColLongText16
+ LikePredicateDbColLongText8TestL(); //EDbColLongText8
+ }
+
+ /**
+@SYMTestCaseID SYSLIB-DBMS-UT-1667
+@SYMTestCaseDesc Testing RdbRowSet::DeleteL() with EDbColLongText16 type columns
+@SYMTestPriority High
+@SYMTestActions Create a table with a EDbColLongText16 type column and then use
+ RdbRowSet::DeleteL() to delete the current row.
+@SYMTestExpectedResults The test should not fail.
+@SYMDEF INC083027
+*/
+LOCAL_C void Defect_INC083027L()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-1667 Defect INC083027 "));
+ RFs fs;
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.Connect());
+
+ // create database
+ RDbNamedDatabase database;
+ CleanupClosePushL(database);
+ User::LeaveIfError(database.Replace(fs, _L("c:\\test.db")));
+
+ CDbColSet* columns = CDbColSet::NewLC();
+ const TInt maxTextLength = 256;
+ TDbCol text16Col(KText16Name, EDbColLongText16, maxTextLength);
+ columns->AddL(text16Col);
+
+ TBuf<KMaxColName> targetColName;
+ targetColName = KText16Name;
+
+ // create table
+ User::LeaveIfError(database.CreateTable(KTableName, *columns));
+
+ //create index
+ CDbKey* key = CDbKey::NewLC();
+ TInt keyLength = 122;
+ TDbKeyCol keyCol(targetColName, keyLength);
+ key->AddL(keyCol);
+ User::LeaveIfError(database.CreateIndex(KIndexName, KTableName, *key));
+ CleanupStack::PopAndDestroy(2); // key and columns
+
+ //insert rows
+ HBufC* sqlQueryBuf = HBufC::NewLC(512);
+ TPtr sqlQuery(sqlQueryBuf->Des());
+ _LIT(KSQLInsertFormat, "SELECT %S FROM %S");
+ sqlQuery.Format(KSQLInsertFormat, &targetColName, &KTableName);
+
+ RDbView insertview;
+ User::LeaveIfError(insertview.Prepare(database, TDbQuery(sqlQuery), RDbView::EInsertOnly));
+
+ HBufC* tmpBuf = HBufC::NewLC(maxTextLength);
+ TPtr maxString(tmpBuf->Des());
+ maxString.Format(KMaxStringFormat, 0);
+ insertview.InsertL();
+ insertview.SetColL(1, maxString);
+ insertview.PutL();
+ insertview.Close();
+
+ //delete the row
+ RDbView deleteview;
+ User::LeaveIfError(deleteview.Prepare(database, TDbQuery(sqlQuery), RDbView::EUpdatable));
+ User::LeaveIfError(deleteview.EvaluateAll());
+
+ while (deleteview.NextL())
+ {
+ deleteview.GetL();
+ TRAPD(err , deleteview.DeleteL());
+ TheTest(err==KErrNone);
+ }
+ deleteview.Close();
+
+ CleanupStack::PopAndDestroy(2); // tmpBuf, sqlQueryBuf
+ CleanupStack::PopAndDestroy(&database); // database
+ CleanupStack::PopAndDestroy(&fs); // fs
+ }
+
+ /**
+@SYMTestCaseID SYSLIB-DBMS-UT-1894
+@SYMTestCaseDesc Testing memory handling in CSqlMultiNode::Concatenate()
+@SYMTestPriority Medium
+@SYMTestActions Execute a special request to a database which will trigger CSqlMultiNode::Concatenate(), and the size of one of the SQL nodes will be divisible by the CSqlMultiNode granularity
+@SYMTestExpectedResults The test should not fail or panic.
+@SYMDEF INC093657
+*/
+LOCAL_C void Defect_INC093657L ()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-1894 Defect INC093657 "));
+ RFs fs;
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.Connect());
+
+ // create database
+ RDbNamedDatabase database;
+ CleanupClosePushL(database);
+ User::LeaveIfError(database.Replace(fs, _L("c:\\test.db")));
+
+ CDbColSet* columns = CDbColSet::NewLC();
+ const TInt maxTextLength = 256;
+ TDbCol column(KColName, EDbColLongText16, maxTextLength);
+ columns->AddL(column);
+
+ // create table
+ User::LeaveIfError(database.CreateTable(KTableName, *columns));
+ CleanupStack::PopAndDestroy(); // columns
+
+ //execute a pointless request that is intended to detect subtle memory corruptions in CSqlMultiNode::Concatenate
+ RDbView view;
+ TInt err = view.Prepare(database, TDbQuery(KSqlRequestGranularity));
+
+ TheTest(err==KErrNone);
+
+ view.Close();
+ database.Destroy();
+
+ CleanupStack::PopAndDestroy(&database); // database
+ CleanupStack::PopAndDestroy(&fs); // fs
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-UT-3467
+@SYMTestCaseDesc Test for DEF105615 "DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory".
+ The test creates a table with 3 coluumns and a multi-column key (3 columns). The column
+ names length is such that when RDbRowSet::ColSetL() is called for retrieving the column
+ names, the CDbColSet array data member will make just a single memory allocation, where
+ all TDbCol elements will be stored. Then the test repeats 100 times, the following statements:
+ <retrieve a colset>;
+ <create a copy of colset's last TDbCol element using TDbCol's copy constructor>;
+ <create a copy of colset's last TDbCol element using TDbCol's "=" operator>;
+ If the test uses the compiler generated TDbCol's copy constructor and "=" operator,
+ the test crashes at some iteration, because an invalid memory region is accessed and
+ the crash is: KERN-EXEC 3.
+ The same test is repeated for TDbKeyCol's copy constructor and "=" operator.
+@SYMTestPriority High
+@SYMTestActions Test for DEF105615 "DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory".
+@SYMTestExpectedResults The test must not fail
+@SYMREQ DEF105615
+*/
+void DEF105615L()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3467 DEF105615 DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory"));
+ RFs fs;
+ TInt err = fs.Connect();
+ TheTest(err == KErrNone);
+
+ RDbNamedDatabase db;
+ err = db.Replace(fs, KDbName);
+ TheTest(err == KErrNone);
+
+ const TInt KColCnt = 3;
+
+ err = db.Execute(_L("CREATE TABLE A(A1234567890 INTEGER, B1234567890 INTEGER, C12345 INTEGER)"));
+ TheTest(err == KErrNone);
+ err = db.Execute(_L("CREATE INDEX I1 ON A(A1234567890, B1234567890, C12345)"));
+ TheTest(err == KErrNone);
+
+ RDbTable tbl;
+ err = tbl.Open(db, _L("A"));
+ TheTest(err == KErrNone);
+
+ //It is very hard to reproduce the problem, because the memory region after the memory, occupied by
+ //CDbColSet's array, may be valid. That is the reason the test is repeated in a loop KTestCnt times,
+ //where every ColSetL() call will allocate a new block of memory for its array and at some point TDbCol's
+ //copy constructor and "=" operator may try to access an invalid memory area, if the compiler generated
+ //ones are used.
+ const TInt KTestCnt = 100;
+ TInt i;
+ CDbColSet* colset[KTestCnt];
+ for(i=0;i<KTestCnt;++i)
+ {
+ TRAP(err, colset[i] = tbl.ColSetL());
+ TheTest(err == KErrNone);
+ TDbCol lastCol = (*colset[i])[KColCnt]; //copy constructor
+ lastCol = (*colset[i])[KColCnt]; //"=" operator
+ }
+ for(i=0;i<KTestCnt;++i)
+ {
+ delete colset[i];
+ }
+
+ tbl.Close();
+
+ //The same test is repeated for TDbKeyCol's copy constructor and "=" operator
+ CDbKey* key[KTestCnt];
+ for(i=0;i<KTestCnt;++i)
+ {
+ TRAP(err, key[i] = db.KeyL(_L("I1"), _L("A")));
+ TheTest(err == KErrNone);
+ TDbKeyCol lastKeyCol = (*key[i])[KColCnt - 1]; //copy constructor
+ lastKeyCol = (*key[i])[KColCnt - 1]; //"=" operator
+ }
+ for(i=0;i<KTestCnt;++i)
+ {
+ delete key[i];
+ }
+
+ db.Close();
+ err = fs.Delete(KDbName);
+ TheTest(err == KErrNone);
+ fs.Close();
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-UT-3469
+@SYMTestCaseDesc Test for DEF105615 "DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory".
+ The test creates TDbCol and TDbKeyCol objects, creates their copies using copy constructors
+ and "=" operators and checks that the copies were constructed correctly,
+@SYMTestPriority High
+@SYMTestActions Test for DEF105615 "DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory".
+@SYMTestExpectedResults The test must not fail
+@SYMREQ DEF105615
+*/
+void DEF105615_2()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3469 DEF105615 DBMS, CDbColSet::operator[](TDbColNo) operator may access an invalid memory - 2 "));
+
+ const TDbColType KColType = EDbColText16;
+ const TInt KMaxColLen = 73;
+ const TInt KColAttributes = TDbCol::ENotNull;
+ _LIT(KColName, "Name");
+
+ TDbCol srcDbCol(KColName, EDbColText16, KMaxColLen);
+ srcDbCol.iAttributes = KColAttributes;
+
+ //TDbCol - copy constructor
+ TDbCol dbColCopy1(srcDbCol);
+ TheTest(dbColCopy1.iType == srcDbCol.iType && dbColCopy1.iType == KColType);
+ TheTest(dbColCopy1.iMaxLength == srcDbCol.iMaxLength && dbColCopy1.iMaxLength == KMaxColLen);
+ TheTest(dbColCopy1.iAttributes == srcDbCol.iAttributes && dbColCopy1.iAttributes == KColAttributes);
+ TheTest(dbColCopy1.iName == srcDbCol.iName && dbColCopy1.iName == KColName);
+
+ //TDbCol - "=" operator
+ TDbCol dbColCopy2;
+ dbColCopy2 = srcDbCol;
+ TheTest(dbColCopy2.iType == srcDbCol.iType && dbColCopy2.iType == KColType);
+ TheTest(dbColCopy2.iMaxLength == srcDbCol.iMaxLength && dbColCopy2.iMaxLength == KMaxColLen);
+ TheTest(dbColCopy2.iAttributes == srcDbCol.iAttributes && dbColCopy2.iAttributes == KColAttributes);
+ TheTest(dbColCopy2.iName == srcDbCol.iName && dbColCopy2.iName == KColName);
+
+ //TDbCol - self assignment
+ srcDbCol = srcDbCol;
+ TheTest(srcDbCol.iType == KColType);
+ TheTest(srcDbCol.iMaxLength == KMaxColLen);
+ TheTest(srcDbCol.iAttributes == KColAttributes);
+ TheTest(srcDbCol.iName == KColName);
+
+ const TInt KKeyLen = 29;
+ const TDbKeyCol::TOrder KKeyOrder = TDbKeyCol::EDesc;
+ _LIT(KKeyName, "Name22");
+
+ TDbKeyCol srcDbKeyCol(KKeyName, KKeyLen, KKeyOrder);
+
+ //TDbKeyCol - copy constructor
+ TDbKeyCol dbKeyColCopy1(srcDbKeyCol);
+ TheTest(dbKeyColCopy1.iOrder == srcDbKeyCol.iOrder && dbKeyColCopy1.iOrder == KKeyOrder);
+ TheTest(dbKeyColCopy1.iLength == srcDbKeyCol.iLength && dbKeyColCopy1.iLength == KKeyLen);
+ TheTest(dbKeyColCopy1.iName == srcDbKeyCol.iName && dbKeyColCopy1.iName == KKeyName);
+
+ //TDbKeyCol - "=" operator
+ TDbKeyCol dbKeyColCopy2;
+ dbKeyColCopy2 = srcDbKeyCol;
+ TheTest(dbKeyColCopy2.iOrder == srcDbKeyCol.iOrder && dbKeyColCopy2.iOrder == KKeyOrder);
+ TheTest(dbKeyColCopy2.iLength == srcDbKeyCol.iLength && dbKeyColCopy2.iLength == KKeyLen);
+ TheTest(dbKeyColCopy2.iName == srcDbKeyCol.iName && dbKeyColCopy2.iName == KKeyName);
+
+ //TDbKeyCol - self assignment
+ srcDbKeyCol = srcDbKeyCol;
+ TheTest(srcDbKeyCol.iOrder == KKeyOrder);
+ TheTest(srcDbKeyCol.iLength == KKeyLen);
+ TheTest(srcDbKeyCol.iName == KKeyName);
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-UT-3413
+@SYMTestCaseDesc Testing that "incremental update" operations running in one connection does not
+ interfere with database operations executed from a second connection
+@SYMTestPriority High
+@SYMTestActions Create a test database with one table and insert some records there (> 100).
+ Create 2 database connections.
+ Open that database from connection 1 and execute an incremental update operation
+ in a transaction. At the same time try to open and close the same table from
+ connection 2, mixing these operations with the RDbUpdate::Next() calls from
+ connection 1. So the call pattern should be:
+ @code
+ RDbUpdate dbUpdate;
+ ....
+ while((err = dbUpdate.Next()) > 0) //from "Conenction 1"
+ {
+ RDbTable tbl;
+ err = tbl.Open(TheDb2, _L("A")); //from "Conenction 2"
+ ...
+ }
+ @endcode
+@SYMTestExpectedResults The test should not fail or panic.
+@SYMDEF INC101720
+*/
+void Defect_INC101720()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3413 "));
+ //Create the test database
+ TInt err = TheDb1.Replace(TheFs, KDbName);
+ TEST2(err, KErrNone);
+ TheDb1.Close();
+ //Establish the first database connection
+ err = TheDbs1.Connect();
+ TEST2(err, KErrNone);
+ err = TheDb1.Open(TheDbs1, KDbName);
+ TEST2(err, KErrNone);
+ //Create a test table and fill the table with enough test records (> 100)
+ err = TheDb1.Execute(_L("CREATE TABLE A(Id COUNTER, Id2 INTEGER, Name LONG VARCHAR)"));
+ TEST2(err, KErrNone);
+ const TInt KTestRecCount = 200;
+ err = TheDb1.Begin();
+ TEST2(err, KErrNone);
+ for(TInt i=0;i<KTestRecCount;++i)
+ {
+ _LIT(KSqlFmtStr, "INSERT INTO A(Id2, Name) VALUES(%d, 'TestNameString')");
+ TBuf<100> sql;
+ TUint32 id = Math::Random() % KTestRecCount;
+ sql.Format(KSqlFmtStr, id + 1);
+ err = TheDb1.Execute(sql);
+ TEST2(err, 1);
+ }
+ err = TheDb1.Commit();
+ TEST2(err, KErrNone);
+ //Establish a second connection with the same test database
+ err = TheDbs2.Connect();
+ TEST2(err, KErrNone);
+ err = TheDb2.Open(TheDbs2, KDbName);
+ TEST2(err, KErrNone);
+ //The test: Conenction 1 - "incremental update" operation.
+ // Connection 2 - "open table/close table" operations mixed with the incremental Next-s.
+ //Expectation: The test must not fail.
+ err = TheDb1.Begin();
+ TEST2(err, KErrNone);
+ RDbUpdate dbUpdate;
+ err = dbUpdate.Execute(TheDb1, _L("UPDATE A SET Name = 'ModifiedNameString' WHERE Id2 > 10"));
+ TEST2(err, KErrNone);
+ TInt step = 0;
+ while((err = dbUpdate.Next()) > 0)
+ {
+ ++step;
+ RDbTable tbl;
+ err = tbl.Open(TheDb2, _L("A"));
+ TEST2(err, KErrNone);
+ tbl.Close();
+ }
+ TEST(step > 1);//just to be sure that the test executes dbUpdate.Next() more than once
+ TEST2(err, KErrNone);
+ dbUpdate.Close();
+ err = TheDb1.Commit();
+ TEST2(err, KErrNone);
+ //Cleanup
+ TheDb2.Close();
+ TheDbs2.Close();
+ TheDb1.Close();
+ TheDbs1.Close();
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-UT-3484
+@SYMTestCaseDesc DBMS Hindi collation doesn't work on long text fields.
+@SYMTestPriority Medium
+@SYMTestActions This test is to check that DBMS correctly sorts columns using Collation, when
+ the columns are of type EDbColLongText16. Previous implementations split the
+ strings to be compared into chunks, however this could cause it to be sorted
+ incorrectly if it was split on a combining or accent character. This fault
+ occurs on the default locale as well as Hindi. Test steps:
+ * Create a database table and adds several unicode strings to EDbColLongText16
+ column in table. One set of strings have an ascii character followed by
+ an accent (e + ') and the other set have the combined equivilant ascii
+ character (è). These should have the same sort order,however if are split
+ then will compare differently.
+ * Sort the columns using EDbCompareCollated
+ * Check that the columns were sorted in the correct order
+@SYMTestExpectedResults The columns should get sorted into ascending order correctly
+@SYMDEF INC107268
+*/
+void Defect_INC107268L()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3484 Defect INC107268 - DBMS Hindi collation doesn't work on long text fields"));
+
+ // some unicode characters
+ const TChar Ka(0x0061); // a
+ const TChar Kb(0x0062); // b
+ const TChar Ke(0x0065); // e
+ const TChar Kgrave(0x0060); // ' (grave)
+ const TChar Kegrave(0x00e8); // e with grave
+ const TChar K1(0x0031); // 1
+ const TChar K2(0x0032); // 2
+
+ // the maximum characters in a EDbColLongText16 string before dbms stops storing
+ // the string inline, and we need to read it from a stream (see TBlobKey).
+ const TInt KInlineLimit = 127;
+
+ // maximum number of characters buffered in TBlobKey when string stored out of line.
+ // (see TBlobKey::ETruncSize which is in bytes)
+ const TInt KTruncLimit = 16;
+
+ const TInt KMaxStringSize = 256;
+
+ TBuf<KMaxStringSize> inLineBoundryA;
+ TBuf<KMaxStringSize> inLineBoundryB;
+ TBuf<KMaxStringSize> truncBoundryA;
+ TBuf<KMaxStringSize> truncBoundryB;
+ TBuf<KMaxStringSize> padding;
+
+ // this string will be stored inline. It should sort to be < stringB
+ inLineBoundryA.Fill(Ka, KInlineLimit-2);
+ inLineBoundryA.Append(Kegrave);
+ inLineBoundryA.Append(K1);
+
+ // this string is just over the break point, so *is* truncated.
+ // this is expected to get sorted incorrecly as combining character is split off (negative test case)
+ inLineBoundryB.Fill(Ka, KInlineLimit-2);
+ inLineBoundryB.Append(Ke);
+ inLineBoundryB.Append(Kgrave);
+ inLineBoundryB.Append(K2);
+
+ padding.Fill(Kb, KInlineLimit);
+
+ // this string is longger that KInlineLimit so is stored out of line
+ truncBoundryA.Fill(Kb, KTruncLimit-2);
+ truncBoundryA.Append(Kegrave);
+ truncBoundryA.Append(K1);
+ truncBoundryA.Append(padding);
+
+ // this string has combining characters that fall on boundry of ETruncSize value (32 bytes)
+ truncBoundryB.Fill(Kb, KTruncLimit-2);
+ truncBoundryB.Append(Ke);
+ truncBoundryB.Append(Kgrave);
+ truncBoundryB.Append(K2);
+ truncBoundryB.Append(padding);
+
+
+ // e and '(grave) characters seperately
+ TBuf<3> e_grave;
+ e_grave.Append( Ke );
+ e_grave.Append( Kgrave );
+
+ // e with grave character - this should sort the same as e_grave
+ TBuf<3> egrave;
+ egrave.Append( Kegrave );
+
+ TBuf<1> nullString;
+
+ e_grave.Append(K2); // make e_grave sort second
+ egrave.Append(K1); // make egrave sort first
+
+ // Check with database
+ _LIT(KPosLmLandmarkTable, "lmt_landmark");
+ _LIT(KPosLmLandmarkIdCol, "lmc_lmid");
+ _LIT(KPosLmNameCol, "lmc_name");
+
+ TInt err = TheDb1.Replace( TheFs, KDbName );
+ TEST2 (err, KErrNone);
+ CleanupClosePushL(TheDb1);
+
+ CDbColSet* columns = CDbColSet::NewLC();
+ TDbCol idField( KPosLmLandmarkIdCol, EDbColUint32 );
+ idField.iAttributes |= TDbCol::EAutoIncrement;
+ columns->AddL( idField );
+ columns->AddL( TDbCol( KPosLmNameCol, EDbColLongText16 ) ); // Works with EDbColText16. Defect only for EDbColLongText16.
+
+ err = TheDb1.CreateTable( KPosLmLandmarkTable, *columns );
+ TEST2 (err, KErrNone);
+ CleanupStack::PopAndDestroy(columns);
+
+ RDbTable table;
+ err = table.Open( TheDb1, KPosLmLandmarkTable );
+ TEST2 (err, KErrNone);
+ CleanupClosePushL(table);
+
+ // add rows to table
+ table.InsertL();
+ table.SetColL( 2, egrave); // row 0 - sorted 8th
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, e_grave ); // row 1 - sorted 9th
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, inLineBoundryA ); // row 2 - sorted 3rd (incorrectly - negative test case)
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, inLineBoundryB ); // row 3 - sorted 2nd (incorrectly - negative test case)
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, nullString ); // row 4 - sorted 1st
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, truncBoundryB ); // row 5 - sorted 5th
+ table.PutL();
+
+ table.InsertL();
+ table.SetColL( 2, truncBoundryA ); // row 6 - sorted 4th
+ table.PutL();
+
+
+ CleanupStack::PopAndDestroy(); // table.close()
+
+ // do an sql select with Order By to sort columns
+ _LIT(KPosLmSqlSelectOrderByString, "SELECT %S, %S FROM %S ORDER BY %S");
+ TBuf<200> sql;
+ sql.Format( KPosLmSqlSelectOrderByString,
+ &KPosLmLandmarkIdCol,
+ &KPosLmNameCol,
+ &KPosLmLandmarkTable,
+ &KPosLmNameCol);
+
+ RDbView view;
+ CleanupClosePushL(view);
+ err = view.Prepare( TheDb1, TDbQuery( sql, EDbCompareCollated ) );
+ TEST2 (err, KErrNone);
+ err = view.EvaluateAll();
+ TEST2 (err, KErrNone);
+
+ // Now check that view is ordered correctly
+ const TUint32 ExpectedOrder[] = {4,3,2,6,5,0,1};
+ TInt x = 0;
+ while (view.NextL())
+ {
+ view.GetL();
+ TEST2(view.ColUint32(1), ExpectedOrder[x]); // check we got the expected order
+ x++;
+ }
+ TEST2(x, 7); // check we got the right number of values
+ CleanupStack::PopAndDestroy(2); // TheDb1.Close(); view.Close()
+ }
+
+
+/**
+@SYMTestCaseID PDS-DBMS-UT-4001
+@SYMTestCaseDesc INC128224 SQL statement with ESCAPE panics in DBMS.
+@SYMTestPriority High
+@SYMTestActions The test verifies that SELECT statement with a LIKE redicate with an ESCAPE clause
+ followed by another LIKE predicate does not causes a crash in DBMS.
+ The test creates a test database, inserts some records and then runs a SELECT
+ statement that has one LIKE predicate with an ESCAPE followed by another LIKE.
+@SYMTestExpectedResults The test should pass and should not crash the DBMS
+@SYMDEF INC128224
+*/
+void INC128224L()
+ {
+ TheTest.Next(_L(" @SYMTestCaseID:PDS-DBMS-UT-4001 INC128224 SQL statement with ESCAPE panics in DBMS"));
+
+ TInt err = TheDb1.Replace(TheFs, KDbName);
+ TEST2(err, KErrNone);
+
+ err = TheDb1.Execute(_L("CREATE TABLE A(T1 VARCHAR(100),T2 VARCHAR(150))"));
+ TEST2(err, KErrNone);
+ err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('AAAAAA','HGS')"));
+ TEST2(err, 1);
+ err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('BBBBBB','RRR')"));
+ TEST2(err, 1);
+ err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('C*CCCCC','AAQWWT')"));
+ TEST2(err, 1);
+ err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('DDDDDD','TUQQPQQQQSSS')"));
+ TEST2(err, 1);
+ err = TheDb1.Execute(_L("INSERT INTO A(T1,T2) VALUES('C*CABS','IAAAIAAAIA')"));
+ TEST2(err, 1);
+
+ RDbView view;
+ err = view.Prepare(TheDb1, _L("SELECT * FROM A WHERE (T1 LIKE '*C\\*C*' ESCAPE '\\') AND (T2 LIKE 'I?A*')"));
+ TEST2(err, KErrNone);
+ TInt cnt = 0;
+ while(view.NextL())
+ {
+ view.GetL();
+ TPtrC t1 = view.ColDes(1);
+ TPtrC t2 = view.ColDes(2);
+ RDebug::Print(_L("T1=\"%S\", T2=\"%S\"\r\n"), &t1, &t2);
+ ++cnt;
+ }
+ view.Close();
+ TEST2(cnt, 1);
+
+ TheDb1.Close();
+ (void)TheFs.Delete(KDbName);
+ }
+
+LOCAL_C void DoTestsL ()
+ {
+ __UHEAP_MARK;
+ CleanupClosePushL(TheFs);
+ Defect_INC076370L();
+ Defect_INC083027L();
+ Defect_DEF44697L ();
+ Defect_INC093657L();
+ Defect_INC101720();
+ DEF105615L();
+ DEF105615_2();
+ Defect_INC107268L();
+ INC128224L();
+ CleanupStack::PopAndDestroy(); // TheFs.Close()
+ __UHEAP_MARKEND;
+ }
+
+
+GLDEF_C TInt E32Main ()
+ {
+ __UHEAP_MARK;
+ TheTest.Title ();
+ TheTest.Start (_L ("Verify Defect Fixes"));
+
+ TheTrapCleanup = CTrapCleanup::New ();
+ __ASSERT_ALWAYS (TheTrapCleanup!=NULL, User::Invariant ());
+
+ TInt err = TheFs.Connect();
+ TheTest(err == KErrNone);
+
+ TRAP (err,DoTestsL ());
+ TheTest (err==KErrNone);
+
+ delete TheTrapCleanup;
+
+ //Wait some time, because DBMS server won't be destroyed right after the last DBMS session
+ //being clossed.
+ TheTest.Printf(_L("Wait DBMS server shutdown...\n"));
+ const TInt KExitDelay = 6000000;
+ User::After(KExitDelay);
+
+ TheTest.End ();
+ TheTest.Close ();
+
+ __UHEAP_MARKEND;
+ return (0);
+ }