--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/tdbms/t_dbsql.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1148 @@
+// Copyright (c) 1998-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:
+//
+
+// MSVC++ up to 5.0 has problems with expanding inline functions
+// This disables the mad warnings for the whole project
+#if defined(NDEBUG) && defined(__VC32__) && _MSC_VER<=1100
+#pragma warning(disable : 4710) // function not expanded. MSVC 5.0 is stupid
+#endif
+
+#include <d32dbms.h>
+#include <f32file.h>
+#include <e32test.h>
+#include <e32math.h>
+
+// constructing literal TInt64 from compiler 64 bit integer rep
+
+#ifndef I64LIT
+#if defined __GCC32__ || defined __EABI__
+#define _LINT64(val) MAKE_TINT64(TUint(val##LL>>32),TUint(val##LL&0xffffffffu))
+#else
+#define _LINT64(val) MAKE_TINT64(TUint(__int64(val)>>32),TUint(__int64(val)&0xffffffffu))
+#endif
+#else // I64LIT
+#define _LINT64 I64LIT
+#endif // I64LIT
+
+LOCAL_D RTest TheTest(_L("t_dbsql: DBMS SQL parsing and execution tests"));
+
+LOCAL_D RFs TheFs;
+LOCAL_D CTrapCleanup* TheTrapCleanup;
+LOCAL_D RDbs TheDbs;
+LOCAL_D RDbNamedDatabase TheDatabase;
+LOCAL_D RDbTable TheTable;
+LOCAL_D RDbView TheView;
+LOCAL_D TBuf<1024> TheSql;
+
+const TInt KTestCleanupStack=0x20;
+const TPtrC KTestDatabase=_L("c:\\dbms-tst\\t_sql.db");
+
+#define elementsof(array) (sizeof(array)/sizeof(array[0]))
+
+LOCAL_C void TestCleanup()
+ {
+ TheTable.Close();
+ TheView.Close();
+ TheDatabase.Close();
+ TheDbs.Close();
+ TheFs.Close();
+ /////////////
+ RFs fsSession;
+ TInt err = fsSession.Connect();
+ if(err == KErrNone)
+ {
+ TEntry entry;
+ if(fsSession.Entry(KTestDatabase, entry) == KErrNone)
+ {
+ RDebug::Print(_L("Deleting \"%S\" file.\n"), &KTestDatabase);
+ err = fsSession.SetAtt(KTestDatabase, 0, KEntryAttReadOnly);
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &KTestDatabase);
+ }
+ err = fsSession.Delete(KTestDatabase);
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &KTestDatabase);
+ }
+ }
+ fsSession.Close();
+ }
+ else
+ {
+ RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &KTestDatabase);
+ }
+ }
+
+LOCAL_C void CloseDatabase()
+ {
+ TheDatabase.Close();
+ }
+
+LOCAL_C void Disconnect()
+ {
+ TheDbs.ResourceCheck();
+ TheDbs.Close();
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+//Tests macros and functions.
+//If (!aValue) then the test will be panicked, the test data files will be deleted.
+static void Check(TInt aValue, TInt aLine)
+ {
+ if(!aValue)
+ {
+ RDebug::Print(_L("*** Expression evaluated to false\r\n"));
+ ::TestCleanup();
+ TheTest(EFalse, aLine);
+ }
+ }
+//If (aValue != aExpected) then the test will be panicked, the test data files will be deleted.
+static 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__)
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+// Create the database
+LOCAL_C void CreateDatabase()
+ {
+ TInt r=TheDatabase.Replace(TheFs,KTestDatabase);
+ TEST2(r, KErrNone);
+ }
+
+LOCAL_C void Connect()
+ {
+ TInt r=TheDbs.Connect();
+ TEST2(r, KErrNone);
+ TheDbs.ResourceMark();
+ }
+
+// Open the database through the server
+LOCAL_C void ShareDatabase()
+ {
+ TInt r=TheDatabase.Open(TheDbs,KTestDatabase);
+ TEST2(r, KErrNone);
+ }
+
+struct TSelectTest
+ {
+ const TText* iSearchCondition;
+ TUint iResultSet;
+ };
+#define ROWS(n,m) (((~0u)<<(n))&((2u<<(m))-1))
+#define ROW(n) ROWS(n,n)
+#define NO_ROWS 0
+#define ALL_ROWS (~1u) // all rows which are not NULL
+
+class TestPredicateBase
+ {
+protected:
+ static void Create(const TText* aType);
+ static void Test(const TSelectTest* aTest,TInt aCount,TInt aRows);
+ static void TestViewL(const TSelectTest* aTest,TInt aCount,TInt aRows);
+ };
+
+// Create the table for the predicate tests
+void TestPredicateBase::Create(const TText* aType)
+ {
+ TheTest.Next(TPtrC(aType));
+ TheDatabase.Begin();
+ TheSql.Format(_L("CREATE TABLE Compare (Id COUNTER,Test %s)"),aType);
+ TInt r=TheDatabase.Execute(TheSql);
+ TEST2(r, KErrNone);
+ r=TheTable.Open(TheDatabase,_L("Compare"),TheTable.EInsertOnly);
+ TEST2(r, KErrNone);
+ }
+
+// Test the predicate on the table, then on the indexed table
+void TestPredicateBase::Test(const TSelectTest* aTest,TInt aCount,TInt aRows)
+ {
+ TheTable.Close();
+ TInt r=TheDatabase.Commit();
+ TEST2(r, KErrNone);
+ TRAPD(errCode, TestViewL(aTest,aCount,aRows));
+ TEST2(errCode, KErrNone);
+ r=TheDatabase.Execute(_L("CREATE INDEX Key ON Compare (Test)"));
+ TEST2(r, KErrNone);
+ TRAP(errCode,TestViewL(aTest,aCount,aRows));
+ TEST2(errCode, KErrNone);
+ r=TheDatabase.Execute(_L("DROP TABLE Compare"));
+ TEST2(r, KErrNone);
+ }
+
+// Test the predicate on the table
+void TestPredicateBase::TestViewL(const TSelectTest* aTest,TInt aCount,TInt aRows)
+ {
+ TUint rowMask=(2u<<aRows)-1;
+ for (;--aCount>=0;++aTest)
+ {
+ TheSql.Format(_L("SELECT Id FROM Compare WHERE Test %s"),aTest->iSearchCondition);
+ TInt r=TheView.Prepare(TheDatabase,TheSql,TheView.EReadOnly);
+
+ TBool ignoreRow0=TheView.Unevaluated();
+ TEST2(r, KErrNone);
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ TUint rows=0;
+ while (TheView.NextL())
+ {
+ TheView.GetL();
+ rows|=1u<<TheView.ColUint(1);
+ }
+ if (ignoreRow0)
+ TEST((rows&~ROW(0))==(aTest->iResultSet&rowMask&~ROW(0)));
+ else
+ TEST(rows==(aTest->iResultSet&rowMask));
+ TheView.Close();
+ }
+ }
+
+typedef void (*FSetColL)(TDbColNo aCol,const TAny* aVal);
+
+void WriteRowsL(const TAny* aValues,TInt aRows,TInt aSize,FSetColL aSetColL)
+ {
+ for (TInt row=0;row<=aRows;++row)
+ {
+ TheTable.InsertL();
+ TEST(TheTable.ColUint(1)==TUint(row));
+ if (row>0)
+ { // first row is always null
+ aSetColL(2,aValues);
+ aValues=PtrAdd(aValues,aSize);
+ }
+ TheTable.PutL();
+ }
+ }
+
+template <class T>
+struct SetCol
+ {
+ static void SetColL(TDbColNo aCol,const TAny* aVal)
+ {
+ TheTable.SetColL(aCol,*(const T*)aVal);
+ }
+ };
+
+template <class T>
+inline void WriteRowsL(const T* aValues,TUint aRows)
+ {
+ WriteRowsL(aValues,aRows,sizeof(T),&SetCol<T>::SetColL);
+ }
+
+template <class T>
+class TestPredicate : public TestPredicateBase
+ {
+public:
+ static void RunL();
+ };
+
+// Test the Predicate operators for all types
+template <class T>
+void TestPredicate<T>::RunL()
+ {
+ Create(T::KType);
+ WriteRowsL(T::KValues,elementsof(T::KValues));
+ Test(T::KTests,elementsof(T::KTests),elementsof(T::KValues));
+ }
+
+struct TypeBit
+ {
+public:
+ static const TText* const KType;
+ static const TUint KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeBit::KType=_S("BIT");
+const TUint TypeBit::KValues[]={0,1};
+const TSelectTest TypeBit::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(1)},
+ {_S("<>0"),ROW(2)},
+ {_S(">0"),ROW(2)},
+ {_S("<0"),NO_ROWS},
+ {_S("<=0"),ROW(1)},
+ {_S(">=0"),ALL_ROWS},
+ {_S("=1"),ROW(2)},
+ {_S("<>1"),ROW(1)},
+ {_S(">1"),NO_ROWS},
+ {_S("<1"),ROW(1)},
+ {_S("<=1"),ALL_ROWS},
+ {_S(">=1"),ROW(2)}
+ };
+
+struct TypeUint8
+ {
+public:
+ static const TText* const KType;
+ static const TUint KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeUint8::KType=_S("UNSIGNED TINYINT");
+const TUint TypeUint8::KValues[]={0,1,127,128,254,255};
+const TSelectTest TypeUint8::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(1)},
+ {_S("=3"),NO_ROWS},
+ {_S("<2"),ROWS(1,2)},
+ {_S(">=0"),ALL_ROWS},
+ {_S("<128"),ROWS(1,3)},
+ {_S("<>1"),ALL_ROWS-ROW(2)},
+ {_S(">255"),NO_ROWS}
+ };
+
+struct TypeUint16
+ {
+public:
+ static const TText* const KType;
+ static const TUint KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeUint16::KType=_S("UNSIGNED SMALLINT");
+const TUint TypeUint16::KValues[]={0,1,5000,32767,32768,65534,65535};
+const TSelectTest TypeUint16::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(1)},
+ {_S("=3"),NO_ROWS},
+ {_S("<2"),ROWS(1,2)},
+ {_S(">=32768"),ROWS(5,7)},
+ {_S("<32767"),ROWS(1,3)},
+ {_S("<>1"),ALL_ROWS-ROW(2)},
+ {_S(">65535"),NO_ROWS}
+ };
+
+struct TypeUint32
+ {
+public:
+ static const TText* const KType;
+ static const TUint KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeUint32::KType=_S("UNSIGNED INTEGER");
+const TUint TypeUint32::KValues[]={0,1,2147483647u,2147483648u,3000000000u,4294967294u,4294967295u};
+const TSelectTest TypeUint32::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(1)},
+ {_S("=3"),NO_ROWS},
+ {_S("<2"),ROWS(1,2)},
+ {_S(">=2147483648"),ROWS(4,7)},
+ {_S("<2147483647"),ROWS(1,2)},
+ {_S("<>3000000000"),ALL_ROWS-ROW(5)},
+ {_S(">4294967295"),NO_ROWS}
+ };
+
+struct TypeInt8
+ {
+public:
+ static const TText* const KType;
+ static const TInt KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeInt8::KType=_S("TINYINT");
+const TInt TypeInt8::KValues[]={-128,-1,0,1,127};
+const TSelectTest TypeInt8::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(3)},
+ {_S("=-1"),ROW(2)},
+ {_S("<2"),ROWS(1,4)},
+ {_S(">=-128"),ALL_ROWS},
+ {_S("<128"),ALL_ROWS},
+ {_S("<>1"),ALL_ROWS-ROW(4)}
+ };
+
+struct TypeInt16
+ {
+public:
+ static const TText* const KType;
+ static const TInt KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeInt16::KType=_S("SMALLINT");
+const TInt TypeInt16::KValues[]={-32768,-32767,-1,0,1,32766,32767};
+const TSelectTest TypeInt16::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(4)},
+ {_S("<>0"),ALL_ROWS-ROW(4)},
+ {_S("=-1"),ROW(3)},
+ {_S("<2"),ROWS(1,5)},
+ {_S(">=-40000"),ALL_ROWS},
+ {_S("<32766"),ROWS(1,5)},
+ {_S("=40"),NO_ROWS}
+ };
+
+struct TypeInt32
+ {
+public:
+ static const TText* const KType;
+ static const TInt KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeInt32::KType=_S("INTEGER");
+const TInt TypeInt32::KValues[]={0x80000000/*-2147483648*/,-2147483647,-1,0,1,2147483646,2147483647};
+const TSelectTest TypeInt32::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(4)},
+ {_S("<>0"),ALL_ROWS-ROW(4)},
+ {_S("=-1"),ROW(3)},
+ {_S("<2"),ROWS(1,5)},
+ {_S(">=-2147483648"),ALL_ROWS},
+ {_S("<2147483646"),ROWS(1,5)},
+ {_S(">2147483647"),NO_ROWS},
+ {_S("=40"),NO_ROWS}
+ };
+
+struct TypeInt64
+ {
+public:
+ static const TText* const KType;
+ static const TInt64 KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeInt64::KType=_S("BIGINT");
+const TInt64 TypeInt64::KValues[]=
+ {
+ MAKE_TINT64(0x80000000, 0x00000000), // min int64
+ _LINT64(-4294967296),
+ TInt(0x80000000), // -2147483648!
+ -1,
+ 0u,
+ 1u,
+ 2147483647u,
+ _LINT64(2147483648),
+ _LINT64(4294967295),
+ _LINT64(4294967296),
+ _LINT64(9223372036854775807) // max int64
+ };
+const TSelectTest TypeInt64::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(5)},
+ {_S("<>0"),ALL_ROWS-ROW(5)},
+ {_S("=-1"),ROW(4)},
+ {_S("<2"),ROWS(1,6)},
+ {_S(">=-9223372036854775808"),ALL_ROWS},
+ {_S("<4294967296"),ROWS(1,9)},
+ {_S(">9223372036854775806"),ROW(11)},
+ {_S("=40"),NO_ROWS}
+ };
+
+struct TypeReal32
+ {
+public:
+ static const TText* const KType;
+ static const TReal32 KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeReal32::KType=_S("REAL");
+const TReal32 TypeReal32::KValues[]=
+ {
+ -KMaxTReal32,
+ -1.0f,
+ -KMinTReal32,
+ 0.0f,
+ KMinTReal32,
+ 1.0f,
+ KMaxTReal32
+ };
+const TSelectTest TypeReal32::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(4)},
+ {_S("<>0.0"),ALL_ROWS-ROW(4)},
+ {_S("=-1"),ROW(2)},
+ {_S("<2e1"),ROWS(1,6)},
+ {_S(">=-100000000000000"),ROWS(2,7)},
+ {_S("<1e-36"),ROWS(1,5)},
+ {_S(">1e15"),ROW(7)},
+ {_S("=.5"),NO_ROWS},
+ {_S("<=-.0"),ROWS(1,4)},
+ {_S("<1e40"),ALL_ROWS}
+ };
+
+struct TypeReal64
+ {
+public:
+ static const TText* const KType;
+ static const TReal64 KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeReal64::KType=_S("DOUBLE");
+const TReal64 TypeReal64::KValues[]=
+ {
+ -KMaxTReal64,
+ -1.0f,
+ -KMinTReal64,
+ 0.0f,
+ KMinTReal64,
+ 1.0f,
+ KMaxTReal64
+ };
+const TSelectTest TypeReal64::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=0"),ROW(4)},
+ {_S("<>0"),ALL_ROWS-ROW(4)},
+ {_S("=-1"),ROW(2)},
+ {_S("<2"),ROWS(1,6)},
+ {_S(">=-100000000000000"),ROWS(2,7)},
+ {_S("<1e-300"),ROWS(1,5)},
+ {_S(">1e15"),ROW(7)},
+ {_S("=.5"),NO_ROWS},
+ {_S("<=0"),ROWS(1,4)},
+ {_S("<1e40"),ROWS(1,6)}
+ };
+
+struct TypeTime
+ {
+public:
+ static const TText* const KType;
+ static const TTime KValues[];
+ static const TSelectTest KTests[];
+ };
+const TText* const TypeTime::KType=_S("TIME");
+const TTime TypeTime::KValues[]=
+ {
+ TInt64(0u), // zero date/time
+ _L(":085815"), // 8:58:15am
+ _L("19181010:110000"), // 11am, 11 Nov 1918
+ _L("19750226:"), // midnight, 27 Mar 1975
+ _L("19961130:235959"), // 11:59:59pm, 31 Dec 1996
+ _L("19970000:"), // midnight, 1 Jan 1997
+ _L("19970611:210000"), // 9pm, 12 July 1997
+ _L("19980309:214500"), // 9:45pm, 10 April 1998
+ _L("20700608:") // midnight, 9 July 2070
+ };
+const TSelectTest TypeTime::KTests[]=
+ {
+ {_S("IS NULL"),ROW(0)},
+ {_S("IS NOT NULL"),ALL_ROWS},
+ {_S("=#12am#"),ROW(1)},
+ {_S("<#Jan 1 2100#"),ALL_ROWS},
+ {_S("<>#31/12/1996 23:59:59#"),ALL_ROWS-ROW(5)},
+ {_S("<#9a#"),ROWS(1,2)},
+ {_S(">=#11:59:59pm, 31 Dec 1996#"),ROWS(5,9)},
+ {_S("=#9:45pm 10 April, 1998#"),ROW(8)},
+ {_S("=#8:58:15#"),ROW(2)}
+ };
+
+struct TypeText
+ {
+public:
+ static const TText* const KType;
+ static const TText* const KValues[];
+ static TSelectTest KTests[];
+ };
+const TText* const TypeText::KType=_S("VARCHAR(100)");
+const TText* const TypeText::KValues[]=
+ {
+ _S(""), // this should be equivalent to NULL
+ _S("a"),
+ _S("aa"),
+ _S("aba"),
+ _S("like"),
+ _S("abcdefghijklmnopqrstuvwxyzlike"),
+ _S("likeabcdefghijklmnopqrstuvwxyz"),
+ _S("abcdefghijklmnopqrstuvwxyzlikeabcdefghijklmnopqrstuvwxyz"),
+ _S("abcdefghijklmnopqrstuvwxyzliveabcdefghijklmnopqrstuvwxyz"),
+ _S("l'ke"),
+ _S("'Tis")
+ };
+TSelectTest TypeText::KTests[]=
+ {
+ {_S("IS NULL"),ROWS(0,1)},
+ {_S("IS NOT NULL"),ALL_ROWS-ROW(1)},
+//
+ {_S("=''"),ROWS(0,1)}, // equivalent to IS NULL
+ {_S("<>''"),ALL_ROWS-ROW(1)}, // equivalent to IS NOT NULL
+ {_S(">''"),ALL_ROWS-ROW(1)}, // equivalent to IS NOT NULL
+ {_S("<''"),NO_ROWS}, // expression is trivially false
+ {_S("<=''"),ROWS(0,1)},
+ {_S(">=''"),ALL_ROWS+ROW(0)}, // expression is trivially true
+//
+ {_S("LIKE ''"),ROWS(0,1)}, // synonomous with IS NULL
+ {_S("NOT LIKE ''"),ALL_ROWS-ROW(1)},
+ {_S("LIKE '?*'"),ALL_ROWS-ROW(1)}, // synonomous with IS NOT NULL
+ {_S("NOT LIKE '?*'"),ROWS(0,1)},
+ {_S("LIKE '*'"),ALL_ROWS+ROW(0)}, // trivially true
+ {_S("NOT LIKE '*'"),NO_ROWS},
+//
+ {_S("='a'"),ROW(2)},
+ {_S("<'ab'"),ROWS(0,3)+ROW(11)},
+ {_S("<'abc'"),ROWS(0,4)+ROW(11)},
+ {_S("<'b'"),ROWS(0,4)+ROW(6)+ROWS(8,9)+ROW(11)},
+ {_S(">'abc'"),ROWS(5,10)},
+ {_S("='like'"),ROW(5)},
+ {_S("='l''ke'"),ROW(10)},
+ {_S("='''Tis'"),ROW(11)},
+//
+ {_S("LIKE 'a'"),ROW(2)},
+ {_S("LIKE 'a*'"),ROWS(2,4)+ROW(6)+ROWS(8,9)},
+ {_S("LIKE '*a'"),ROWS(2,4)},
+ {_S("LIKE 'a*a'"),ROWS(3,4)},
+ {_S("LIKE '*a*'"),ROWS(2,4)+ROWS(6,9)},
+//
+ {_S("LIKE 'like'"),ROW(5)},
+ {_S("LIKE 'l?ke'"),ROW(5)+ROW(10)},
+ {_S("LIKE 'like*'"),ROW(5)+ROW(7)},
+ {_S("LIKE '*like'"),ROWS(5,6)},
+ {_S("LIKE '*like*'"),ROWS(5,8)},
+ {_S("LIKE '*likeit*'"),NO_ROWS},
+ {_S("LIKE '*li?e*'"),ROWS(5,9)},
+ {_S("LIKE '?*li?e*'"),ROW(6)+ROWS(8,9)},
+ {_S("LIKE '*li?e*?'"),ROWS(7,9)},
+ {_S("LIKE '?*li?e*?'"),ROWS(8,9)},
+ {_S("LIKE '*?k?*'"),ROWS(5,10)},
+ {_S("LIKE '*?i?e*'"),ROWS(5,9)},
+//
+ {_S("LIKE '*e*'"),ROWS(5,10)},
+ {_S("LIKE '*z*k*e*'"),ROW(6)+ROW(8)},
+ {_S("LIKE '\?\?k?'"),ROW(5)+ROW(10)},
+ {_S("LIKE '\?\?k*'"),ROW(5)+ROW(7)+ROW(10)},
+ {_S("LIKE '*''*'"),ROWS(10,11)},
+ {_S("LIKE '?''\?\?'"),ROW(10)},
+ {_S("LIKE '?'"),ROW(2)},
+ {_S("LIKE '\?\?\?\?'"),ROW(5)+ROWS(10,11)},
+ {_S("LIKE '\?\?*\?\?'"),ROWS(5,11)},
+ {_S("LIKE '''*'"),ROW(11)}
+ };
+
+TEMPLATE_SPECIALIZATION struct SetCol<const TText* const>
+ {
+ static void SetColL(TDbColNo aCol,const TAny* aVal)
+ {
+ TheTable.SetColL(aCol,TPtrC(*(const TText* const*)aVal));
+ }
+ };
+TEMPLATE_SPECIALIZATION struct SetCol<const TText*>
+ {
+ static void SetColL(TDbColNo aCol,const TAny* aVal)
+ {
+ TheTable.SetColL(aCol,TPtrC(*(const TText* const*)aVal));
+ }
+ };
+
+struct TypeLongText
+ {
+public:
+ static const TText* const KType;
+ };
+const TText* const TypeLongText::KType=_S("LONG VARCHAR");
+
+class TestPredicate2 : public TestPredicateBase
+ {
+public:
+ static void RunL();
+ };
+
+// write rows equivalent to TypeText and use its tests
+void TestPredicate2::RunL()
+ {
+ Create(TypeLongText::KType);
+ TBuf<1022> fill=_S("abcdefghijklmnopqrstuvqxyz");
+ fill.AppendFill('.',fill.MaxLength()-fill.Length());
+
+ for (TInt row=0;row<=TInt(elementsof(TypeText::KValues));++row)
+ {
+ TheTable.InsertL();
+ TheTable.SetColL(1,row);
+ if (row>0)
+ {
+ RDbColWriteStream blob;
+ blob.OpenLC(TheTable,2);
+ switch (row)
+ {
+ case 0:
+ break;
+ case 1: case 2: case 3: case 4: case 5: case 10: case 11:
+ blob.WriteL(TPtrC(TypeText::KValues[row-1]));
+ break;
+ case 6:
+ blob.WriteL(fill);
+ blob.WriteL(_L("like"));
+ break;
+ case 7:
+ blob.WriteL(_L("like"));
+ blob.WriteL(fill);
+ break;
+ case 8:
+ blob.WriteL(fill);
+ blob.WriteL(_L("like"));
+ blob.WriteL(fill);
+ break;
+ case 9:
+ blob.WriteL(fill);
+ blob.WriteL(_L("live"));
+ blob.WriteL(fill);
+ break;
+ }
+ blob.CommitL();
+ CleanupStack::PopAndDestroy();
+ }
+ TheTable.PutL();
+ }
+ TheTable.Close();
+ TInt r=TheDatabase.Commit();
+ TEST2(r, KErrNone);
+ TestViewL(TypeText::KTests,elementsof(TypeText::KTests),elementsof(TypeText::KValues));
+ CDbKey& key=*CDbKey::NewLC();
+ key.AddL(TDbKeyCol(_L("Test"),120));
+ r=TheDatabase.CreateIndex(_L("Key"),_L("Compare"),key);
+ TEST2(r, KErrNone);
+ CleanupStack::PopAndDestroy();
+ TestViewL(TypeText::KTests,elementsof(TypeText::KTests),elementsof(TypeText::KValues));
+ r=TheDatabase.Execute(_L("DROP TABLE Compare"));
+ TEST2(r, KErrNone);
+ }
+
+/**
+* Utility for DEF063276 fix.
+*/
+
+_LIT(KTypeTextKTests44, "Z:\\test\\TypeTextKTests44.dat");
+_LIT(KTypeTextKTests46, "Z:\\test\\TypeTextKTests46.dat");
+_LIT(KTypeTextKTests47, "Z:\\test\\TypeTextKTests47.dat");
+
+static void ReadDesc(TDes& aDes, const TDesC& aFilename, RFs& aFs)
+ {
+ RDebug::Print(_L("---ReadDesc(), aFilename=%S\r\n"), &aFilename);
+ RFile file;
+ TInt err = file.Open(aFs, aFilename, EFileRead);
+ TEST2(err, KErrNone);
+
+ TPtr8 ptr(reinterpret_cast<TUint8*>(const_cast<TUint16*>(aDes.Ptr())), aDes.MaxSize());
+ err = file.Read(ptr);
+ TEST2(err, KErrNone);
+ aDes.SetLength(ptr.Length() / sizeof(TText));
+ file.Close();
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-CT-0633
+@SYMTestCaseDesc Tests the Predicate operators for all types
+@SYMTestPriority Medium
+@SYMTestActions Attempt to check with different types
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ0000
+*/
+LOCAL_C void TestPredicatesL()
+ {
+ TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0633 init "));
+ CreateDatabase();
+ TestPredicate<TypeBit>::RunL();
+ TestPredicate<TypeUint8>::RunL();
+ TestPredicate<TypeUint16>::RunL();
+ TestPredicate<TypeUint32>::RunL();
+ TestPredicate<TypeInt8>::RunL();
+ TestPredicate<TypeInt16>::RunL();
+ TestPredicate<TypeInt32>::RunL();
+ TestPredicate<TypeInt64>::RunL();
+ TestPredicate<TypeReal32>::RunL();
+ TestPredicate<TypeReal64>::RunL();
+ TestPredicate<TypeTime>::RunL();
+
+ /**
+ * Work around for DEF063276.
+ * These literals are now loaded from Z:\test\TypeTextKTests44.dat,
+ * Z:\test\data\TypeTextKTests44.dat and Z:\test\TypeTextKTests44.dat respectively.
+ * Bullseye Coverage corrupts these literals to avoid this they are stored in files as to not be touched by Bullseye Coverage.
+ */
+
+ TBuf<16> buf44;
+ ReadDesc(buf44, KTypeTextKTests44, TheFs);
+ TypeText::KTests[44].iSearchCondition = const_cast<TText*>(buf44.PtrZ());
+
+ TBuf<32> buf46(TypeText::KTests[46].iSearchCondition);
+ ReadDesc(buf46, KTypeTextKTests46, TheFs);
+ TypeText::KTests[46].iSearchCondition = const_cast<TText*>(buf46.PtrZ());
+
+ TBuf<32> buf47(TypeText::KTests[47].iSearchCondition);
+ ReadDesc(buf47, KTypeTextKTests47, TheFs);
+ TypeText::KTests[47].iSearchCondition = const_cast<TText*>(buf47.PtrZ());
+
+ // End fix.
+
+ TestPredicate<TypeText>::RunL();
+ TestPredicate2::RunL();
+ CloseDatabase();
+ TheTest.End();
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-CT-0634
+@SYMTestCaseDesc DML Query test
+ Test for RDbNamedDatabase::Execute() function
+@SYMTestPriority Medium
+@SYMTestActions Tests for CREATE TABLE,CREATE UNIQUE INDEX,INSET INTO,UPDATE,DELETE,DROP queries
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ0000
+*/
+LOCAL_C void TestDataModificationlanguage()
+ {
+ TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0634 init "));
+ Connect();
+ ShareDatabase();
+ TInt r=TheDatabase.Execute(_L("CREATE TABLE test (ID INTEGER NOT NULL,SALARY DOUBLE)"));
+ TEST2(r, KErrNone);
+ r=TheDatabase.Execute(_L("CREATE UNIQUE INDEX key ON test (ID)"));
+ TEST2(r, KErrNone);
+
+ TheTest.Next(_L("insert-statements"));
+ r=TheDatabase.Execute(_L("INSERT INTO test VALUES (0,0)"));
+ TEST(r==1);
+ r=TheDatabase.Execute(_L("INSERT INTO test (ID) VALUES (1)"));
+ TEST(r==1);
+ r=TheDatabase.Execute(_L("INSERT INTO test (SALARY,ID) VALUES (20.4,2)"));
+ TEST(r==1);
+
+ TheTest.Next(_L("update-statements"));
+ r=TheDatabase.Execute(_L("UPDATE test SET SALARY=30000 WHERE ID=1"));
+ TEST(r==1);
+
+ TheTest.Next(_L("delete-statements"));
+ r=TheDatabase.Execute(_L("DELETE FROM test WHERE SALARY<40"));
+ TEST(r==2);
+ r=TheDatabase.Execute(_L("DELETE FROM test"));
+ TEST(r==1);
+ r=TheDatabase.Execute(_L("DROP TABLE test"));
+ TEST2(r, KErrNone);
+//
+ TheTest.Next(_L("larger table"));
+ r=TheDatabase.Execute(_L("CREATE TABLE test (ID COUNTER,DATA INTEGER)"));
+ TEST2(r, KErrNone);
+
+ TheTest.Next(_L("insert"));
+ r=TheDatabase.Begin();
+ TEST2(r, KErrNone);
+ TBuf<256> sql;
+ for (TInt ii=0;ii<100;++ii)
+ {
+ sql.Format(_L("INSERT INTO test (DATA) VALUES (%D)"),100-ii);
+ r=TheDatabase.Execute(sql);
+ TEST(r==1);
+ }
+ r=TheDatabase.Commit();
+ TEST2(r, KErrNone);
+
+ TheTest.Next(_L("update"));
+ r=TheDatabase.Execute(_L("UPDATE test SET DATA=200 WHERE ID>=40 AND ID<60"));
+ TEST(r==20);
+
+ TheTest.Next(_L("delete"));
+ r=TheDatabase.Execute(_L("DELETE FROM test WHERE DATA>90"));
+ TEST(r==30);
+
+ TheTest.Next(_L("update"));
+ r=TheDatabase.Execute(_L("UPDATE test SET DATA=-1"));
+ TEST(r==70);
+
+ TheTest.Next(_L("delete"));
+ r=TheDatabase.Execute(_L("DELETE FROM test"));
+ TEST(r==70);
+ r=TheDatabase.Execute(_L("DROP TABLE test"));
+ TEST2(r, KErrNone);
+ CloseDatabase();
+ Disconnect();
+ TheTest.End();
+ }
+
+/**
+@SYMTestCaseID SYSLIB-DBMS-CT-0635
+@SYMTestCaseDesc DBMS SQL parsing and execution tests.Tests for database index order
+ Test for RDbNamedDatabase::Execute() function
+@SYMTestPriority Medium
+@SYMTestActions Tests for order by index
+@SYMTestExpectedResults Test must not fail
+@SYMREQ REQ0000
+*/
+LOCAL_C void TestOrderByL()
+ {
+ static const TReal TestDataSalary[]={10,34000,15000,53200,17800,240000};
+ static const TText* const TestDataNames[]={_S("gopher"),_S("james '007' bond"),_S("moneypenny"),_S("Q"),_S("james '007' bond"),_S("M")};
+//
+ TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0635 init "));
+ Connect();
+ ShareDatabase();
+ TheDatabase.Begin();
+ TInt r=TheDatabase.Execute(_L("CREATE TABLE test (ID INTEGER NOT NULL,SALARY DOUBLE,NAME VARCHAR)"));
+ TEST2(r, KErrNone);
+ r=TheDatabase.Execute(_L("CREATE UNIQUE INDEX key ON test (ID)"));
+ TEST2(r, KErrNone);
+
+ TheTest.Next(_L("insert data"));
+ r=TheView.Prepare(TheDatabase,_L("SELECT ID,SALARY,NAME FROM test"),TheView.EInsertOnly);
+ TEST2(r, KErrNone);
+ TInt ii;
+ for (ii=0;ii<6;++ii)
+ {
+ TheView.InsertL();
+ TheView.SetColL(1,6-ii);
+ TheView.SetColL(2,TestDataSalary[ii]);
+ TheView.SetColL(3,TPtrC(TestDataNames[ii]));
+ TheView.PutL();
+ }
+ r=TheDatabase.Commit();
+ TEST2(r, KErrNone);
+ TheView.Close();
+
+ TheTest.Next(_L("Order by <index>"));
+ // test the index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT ID FROM test ORDER BY ID"));
+ TEST2(r, KErrNone);
+ TEST(!TheView.Unevaluated());
+ TInt c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TInt last=TheView.ColInt(1);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TInt v=TheView.ColInt(1);
+ TEST(v>last);
+ last=v;
+ }
+ }
+ TEST(c==6);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+
+ TheTest.Next(_L("Order by <no-index> 1"));
+ // test that no index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT SALARY FROM test ORDER BY SALARY"));
+ TEST2(r, KErrNone);
+ TEST(TheView.Unevaluated());
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal last=TheView.ColReal(1);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal v=TheView.ColReal(1);
+ TEST(v>=last);
+ last=v;
+ }
+ }
+ TEST(c==6);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+
+ TheTest.Next(_L("Order by <no-index> 2"));
+ // test that no index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT SALARY FROM test ORDER BY SALARY,NAME"));
+ TEST2(r, KErrNone);
+ TEST(TheView.Unevaluated());
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal last=TheView.ColReal(1);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal v=TheView.ColReal(1);
+ TEST(v>=last);
+ last=v;
+ }
+ }
+ TEST(c==6);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+
+ TheTest.Next(_L("Order by <no-index> 3"));
+ // test that no index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT NAME FROM test ORDER BY NAME"));
+ TEST2(r, KErrNone);
+ TEST(TheView.Unevaluated());
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TBuf<50> last=TheView.ColDes(1);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TPtrC v=TheView.ColDes(1);
+ TEST(v>=last);
+ last=v;
+ }
+ }
+ TEST(c==6);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+
+ TheTest.Next(_L("Order by <no-index> 4"));
+ // test that no index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT NAME FROM test ORDER BY NAME,SALARY"));
+ TEST2(r, KErrNone);
+ TEST(TheView.Unevaluated());
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TBuf<50> last=TheView.ColDes(1);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TPtrC v=TheView.ColDes(1);
+ TEST(v>=last);
+ last=v;
+ }
+ }
+ TEST(c==6);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+
+ TheTest.Next(_L("Order by + search <no-index>"));
+ // test that no index is used here
+ r=TheView.Prepare(TheDatabase,_L("SELECT ID,SALARY FROM test WHERE SALARY>30000 ORDER BY SALARY DESC"));
+ TEST2(r, KErrNone);
+ TEST(TheView.Unevaluated());
+ r=TheView.EvaluateAll();
+ TEST2(r, KErrNone);
+ c=0;
+ if (TheView.FirstL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal last=TheView.ColReal(2);
+ while (TheView.NextL())
+ {
+ ++c;
+ TheView.GetL();
+ TReal v=TheView.ColReal(2);
+ TEST(v<=last);
+ last=v;
+ }
+ }
+ TEST(c==3);
+ TEST(c==TheView.CountL());
+ TheView.Close();
+//
+ CloseDatabase();
+ Disconnect();
+
+ TheTest.Next(_L("Order by <index> Finished"));
+ TheTest.End();
+ }
+
+LOCAL_C void doMain()
+ {
+ TheTest.Start(_L("Predicate tests"));
+ TRAPD(errCode, TestPredicatesL());
+ TEST2(errCode, KErrNone);
+
+ TheTest.Next(_L("DML execution"));
+ TestDataModificationlanguage();
+
+ TheTest.Next(_L("ORDER BY clause"));
+ TRAP(errCode, TestOrderByL());
+ TEST2(errCode, KErrNone);
+ TheTest.End();
+ }
+
+// Prepare the test directory.
+LOCAL_C void setupTestDirectory()
+ {
+ TInt r=TheFs.Connect();
+ TEST2(r, KErrNone);
+//
+ r=TheFs.MkDir(KTestDatabase);
+ TEST(r==KErrNone || r==KErrAlreadyExists);
+ }
+
+// Initialise the cleanup stack.
+LOCAL_C void setupCleanup()
+ {
+ TheTrapCleanup=CTrapCleanup::New();
+ TEST(TheTrapCleanup!=NULL);
+ TRAPD(r,\
+ {\
+ for (TInt i=KTestCleanupStack;i>0;i--)\
+ CleanupStack::PushL((TAny*)0);\
+ CleanupStack::Pop(KTestCleanupStack);\
+ });
+ TEST2(r, KErrNone);
+ }
+
+// Test streaming conversions.
+GLDEF_C TInt E32Main()
+ {
+ TheTest.Title();
+ setupTestDirectory();
+ setupCleanup();
+ __UHEAP_MARK;
+//
+ TheTest.Start(_L("Standard database"));
+ doMain();
+
+ // clean up data file used by this test - must be done before call to End() - DEF047652
+ ::TestCleanup();
+ TheTest.End();
+//
+ __UHEAP_MARKEND;
+
+
+ delete TheTrapCleanup;
+ TheTest.Close();
+ return 0;
+ }