First public contribution.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 LOCAL_D RTest test(_L("t_dbalter : Test AlterTable"));
21 LOCAL_D CTrapCleanup* TheTrapCleanup;
22 LOCAL_D CFileStore* TheStore;
23 LOCAL_D RDbStoreDatabase TheDatabase;
24 LOCAL_D RDbTable TheTable;
27 const TInt KTestCleanupStack=0x20;
28 const TPtrC KTestDir=_L("C:\\DBMS-TST\\");
29 const TPtrC KTestFile=_L("T_ALTER.DB");
30 const TPtrC KTableName(_S("Table"));
31 const TPtrC KTableName2(_S("Table2"));
32 const TPtrC KIndexName(_S("Index"));
36 const TUint KCol1Data=0;
37 const TInt KCol2Data=2;
38 const TPtrC KCol3Data=_L("three");
39 const TUint8 _Col4Data[80]={4,4,4,4,0,0xff,2,2,1};
40 const TPtrC8 KCol4Data(_Col4Data,sizeof(_Col4Data));
41 const TUint KCol5Data=1;
42 const TInt KCol6Data=5;
43 const TPtrC KCol7Data=_L("six");
44 const TPtrC KCol8Data=_L("column number eight = #8");
45 const TUint8 _Col9Data[400]={1,2,3,4,5,6,7,8,9,10};
46 const TPtrC8 KCol9Data(_Col9Data,sizeof(_Col9Data));
48 const TText* const KColumn1=_S("c1");
49 const TText* const KColumn2=_S("c2");
50 const TText* const KColumn3=_S("c3");
51 const TText* const KColumn4=_S("c4");
52 const TText* const KColumn5=_S("c5");
53 const TText* const KColumn6=_S("c6");
54 const TText* const KColumn7=_S("c7");
55 const TText* const KColumn8=_S("c8");
56 const TText* const KColumn9=_S("c9");
57 const TText* const KColumn10=_S("c10");
58 const TText* const KColumn11=_S("c11");
59 const TPtrC KColumns[]=
82 static SColDef const Basic[];
83 static SColDef const Bad[];
84 static SColDef const Incompatible1[];
85 static SColDef const Incompatible2[];
86 static SColDef const Incompatible3[];
87 static SColDef const Different[];
88 static SColDef const Extended[];
89 static SColDef const LongerText[];
90 static SColDef const TextToLongText[];
91 static SColDef const Column3[];
92 static SColDef const DropSome[];
93 static SColDef const DropAndAdd[];
95 static CDbColSet* CreateL(const SColDef* aDef);
97 // the basic column definition
98 enum TCol {EBit,EInt,EText,ELong,EBitNull,EIntNull,ETextNull,ELongNull,EExtra};
99 Set::SColDef const Set::Basic[]=
101 {KColumn1,EDbColBit,TDbCol::ENotNull,-1},
102 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
103 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
104 {KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
105 {KColumn5,EDbColBit,0,-1},
106 {KColumn6,EDbColInt32,0,-1},
107 {KColumn7,EDbColText,0,-1},
108 {KColumn8,EDbColText,0,50},
111 // a basically invalid set
112 Set::SColDef const Set::Bad[]=
114 {KColumn9,EDbColInt32,0,-1},
115 {KColumn9,EDbColInt32,0,-1},
118 // an incompatible set with Basic
119 Set::SColDef const Set::Incompatible1[]=
121 {KColumn1,EDbColInt32,TDbCol::ENotNull,-1}, // retype a column
124 Set::SColDef const Set::Incompatible2[]=
126 {KColumn5,EDbColBit,TDbCol::ENotNull,-1}, // change attributes
129 Set::SColDef const Set::Incompatible3[]=
131 {KColumn8,EDbColText,0,49}, // shrink a text column
134 // a wildly different set
135 Set::SColDef const Set::Different[]=
137 {KColumn11,EDbColInt32,0,-1},
138 {KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
139 {KColumn10,EDbColBit,TDbCol::ENotNull,-1},
140 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
144 Set::SColDef const Set::Extended[]=
146 {KColumn1,EDbColBit,TDbCol::ENotNull,-1},
147 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
148 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
149 {KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
150 {KColumn5,EDbColBit,0,-1},
151 {KColumn6,EDbColInt32,0,-1},
152 {KColumn7,EDbColText,0,-1},
153 {KColumn8,EDbColText,0,50},
154 {KColumn9,EDbColLongBinary,0,-1}, // add this column
157 // Extended with a longer text column
158 Set::SColDef const Set::LongerText[]=
160 {KColumn1,EDbColBit,TDbCol::ENotNull,-1},
161 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
162 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
163 {KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
164 {KColumn5,EDbColBit,0,-1},
165 {KColumn6,EDbColInt32,0,-1},
166 {KColumn7,EDbColText,0,-1},
167 {KColumn8,EDbColText,0,51}, // longer definition
168 {KColumn9,EDbColLongBinary,0,-1},
171 // Extended with a text->LongText column
172 Set::SColDef const Set::TextToLongText[]=
174 {KColumn1,EDbColBit,TDbCol::ENotNull,-1},
175 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
176 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
177 {KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
178 {KColumn5,EDbColBit,0,-1},
179 {KColumn6,EDbColInt32,0,-1},
180 {KColumn7,EDbColText,0,-1},
181 {KColumn8,EDbColLongText,0,-1}, // longer still
182 {KColumn9,EDbColLongBinary,0,-1},
185 Set::SColDef const Set::Column3[]=
187 {KColumn3,EDbColText,TDbCol::ENotNull,-1},
190 Set::SColDef const Set::DropSome[]=
192 {KColumn1,EDbColBit,TDbCol::ENotNull,-1},
193 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
194 {KColumn6,EDbColInt32,0,-1},
195 {KColumn7,EDbColText,0,-1},
198 Set::SColDef const Set::DropAndAdd[]=
200 {KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
201 {KColumn7,EDbColText,0,-1},
202 {KColumn10,EDbColBinary,0,-1},
206 CDbColSet* Set::CreateL(const SColDef* aDef)
208 CDbColSet *set=CDbColSet::NewLC();
209 for (;aDef->iName;++aDef)
211 TDbCol col(TPtrC(aDef->iName),aDef->iType);
212 col.iAttributes=aDef->iAttributes;
213 if (aDef->iMaxLength>=0)
214 col.iMaxLength=aDef->iMaxLength;
222 // Create the database-in-a-store
224 LOCAL_C void CreateDatabaseL()
226 CFileStore* store=CPermanentFileStore::ReplaceLC(TheFs,KTestFile,EFileRead|EFileWrite);
227 store->SetTypeL(KPermanentFileStoreLayoutUid);
229 id=TheDatabase.CreateL(store);
237 // Open the database-in-a-store
239 LOCAL_C void OpenDatabaseL()
241 CFileStore* store=CFileStore::OpenLC(TheFs,KTestFile,EFileRead|EFileWrite);
242 TStreamId id=store->Root();
243 TheDatabase.OpenL(store,id);
248 LOCAL_C void CloseDatabaseL()
254 LOCAL_C void DestroyDatabaseL()
256 TheDatabase.Destroy();
261 LOCAL_C CDbColSet* TableDefinitionL(const TDesC& aTable)
264 test(table.Open(TheDatabase,aTable,table.EReadOnly)==KErrNone);
265 CDbColSet* cs=table.ColSetL();
271 // Compare two column sets
273 LOCAL_C void Compare(const CDbColSet& aLeft,const CDbColSet& aRight)
275 test(aLeft.Count()==aRight.Count());
276 for (TDbColSetIter iter(aLeft);iter;++iter)
278 const TDbCol* pRight=aRight.Col(iter->iName);
280 test(iter->iType==pRight->iType);
281 test(iter->iMaxLength==KDbUndefinedLength || pRight->iMaxLength==KDbUndefinedLength || iter->iMaxLength==pRight->iMaxLength);
282 test((iter->iAttributes&pRight->iAttributes)==iter->iAttributes);
287 @SYMTestCaseID SYSLIB-DBMS-CT-0575
288 @SYMTestCaseDesc Store database test
289 Test for altering the table with different column definitions
290 @SYMTestPriority Medium
291 @SYMTestActions Test for RDbStoreDatabase::AlterTable(),RDbStoreDatabase::DropIndex()
292 @SYMTestExpectedResults Test must not fail
295 LOCAL_C void TestEmptyTableL()
297 test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0575 Create table "));
299 CDbColSet* set=Set::CreateL(Set::Basic);
300 test(TheDatabase.CreateTable(KTableName,*set)==KErrNone);
301 test.Next(_L("Alter non existant table"));
302 test(TheDatabase.AlterTable(KTableName2,*set)==KErrNotFound);
305 test.Next(_L("Alter to bad definitions"));
306 set=Set::CreateL(Set::Bad);
307 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
309 set=Set::CreateL(Set::Incompatible1);
310 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
312 set=Set::CreateL(Set::Incompatible2);
313 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
315 set=Set::CreateL(Set::Incompatible3);
316 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
319 test.Next(_L("Drop an indexed column"));
320 CDbKey* key=CDbKey::NewLC();
321 key->AddL(TPtrC(KColumn2));
323 test(TheDatabase.CreateIndex(KIndexName,KTableName,*key)==KErrNone);
324 CleanupStack::PopAndDestroy();
325 set=TableDefinitionL(KTableName);
326 set->Remove(TPtrC(KColumn2));
327 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
328 test(TheDatabase.DropIndex(KIndexName,KTableName)==KErrNone);
331 test.Next(_L("Extend an indexed text column"));
332 set=Set::CreateL(Set::Extended);
333 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
336 key->AddL(TPtrC(KColumn8));
338 test(TheDatabase.CreateIndex(KIndexName,KTableName,*key)==KErrNone);
339 CleanupStack::PopAndDestroy();
340 set=Set::CreateL(Set::LongerText);
341 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
342 test(TheDatabase.DropIndex(KIndexName,KTableName)==KErrNone);
344 test.Next(_L("Extend a text column"));
345 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
348 test.Next(_L("Extend a text column to a LongText column"));
349 set=Set::CreateL(Set::TextToLongText);
350 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
353 test.Next(_L("Alter to a very different set"));
354 set=Set::CreateL(Set::Different);
355 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
358 CDbColSet* def=TableDefinitionL(KTableName);
363 test(TheDatabase.DropTable(KTableName)==KErrNone);
371 void Init(RDbRowSet& aSet);
372 inline TDbColNo operator[](TInt aCol) const
375 TDbColNo iMap[EExtra+1];
382 void Map::Init(RDbRowSet& aSet)
385 TRAPD(errCode, set=aSet.ColSetL());
386 if(errCode != KErrNone)
390 for (TInt ii=EBit;ii<=EExtra;++ii)
391 iMap[ii]=set->ColNo(KColumns[ii]);
397 // Build the table for Altering
399 LOCAL_C void BuildTableL(const Set::SColDef* aDef=Set::Basic)
401 CDbColSet* set=Set::CreateL(aDef);
402 test(TheDatabase.CreateTable(KTableName,*set)==KErrNone);
405 test(TheTable.Open(TheDatabase,KTableName,TheTable.EInsertOnly)==KErrNone);
408 for (TInt ii=0;ii<KRecords;++ii)
411 TheTable.SetColL(map[EBit],KCol1Data);
412 TheTable.SetColL(map[EInt],KCol2Data);
413 TheTable.SetColL(map[EText],KCol3Data);
414 TheTable.SetColL(map[ELong],KCol4Data);
415 if ((ii%EBitNull)==0)
416 TheTable.SetColL(map[EBitNull],KCol5Data);
417 if ((ii%EIntNull)==0)
418 TheTable.SetColL(map[EIntNull],KCol6Data);
419 if ((ii%ETextNull)==0)
420 TheTable.SetColL(map[ETextNull],KCol7Data);
421 if ((ii%ELongNull)==0)
422 TheTable.SetColL(map[ELongNull],KCol8Data);
423 if (map[EExtra] && (ii%EExtra)==0)
424 TheTable.SetColL(map[EExtra],KCol9Data);
428 test(TheDatabase.Commit()==KErrNone);
431 LOCAL_C void CheckBlobL(TDbColNo aCol,const TDesC8& aData)
433 test(TheTable.ColSize(aCol)==aData.Size());
435 __ASSERT_DEBUG(buf.MaxLength()>=aData.Length(),User::Invariant());
436 RDbColReadStream str;
437 str.OpenLC(TheTable,aCol);
438 str.ReadL(buf,aData.Length());
439 CleanupStack::PopAndDestroy();
444 LOCAL_C void CheckBlobL(TDbColNo aCol,const TDesC16& aData)
446 test(TheTable.ColSize(aCol)==aData.Size());
448 __ASSERT_DEBUG(buf.MaxLength()>=aData.Length(),User::Invariant());
449 RDbColReadStream str;
450 str.OpenLC(TheTable,aCol);
451 str.ReadL(buf,aData.Length());
452 CleanupStack::PopAndDestroy();
458 // Check that the columns which still exist, still contain the same stuff
459 // New columns should be Null
461 LOCAL_C void CheckTableL()
463 test(TheTable.Open(TheDatabase,KTableName,TheTable.EReadOnly)==KErrNone);
467 for (TInt ii=0;ii<KRecords;++ii)
469 test(TheTable.NextL());
472 test(TheTable.ColUint(map[EBit])==KCol1Data);
474 test(TheTable.ColInt(map[EInt])==KCol2Data);
476 test(TheTable.ColDes(map[EText])==KCol3Data);
478 CheckBlobL(map[ELong],KCol4Data);
479 for (TInt jj=EBitNull;jj<=EExtra;++jj)
484 test(TheTable.IsColNull(map[jj]));
490 test(TheTable.ColUint(map[EBitNull])==KCol5Data);
493 test(TheTable.ColInt(map[EIntNull])==KCol6Data);
496 test(TheTable.ColDes(map[ETextNull])==KCol7Data);
499 CheckBlobL(map[ELongNull],KCol8Data);
502 CheckBlobL(map[EExtra],KCol9Data);
512 @SYMTestCaseID SYSLIB-DBMS-CT-0576
513 @SYMTestCaseDesc Test a full table
514 @SYMTestPriority Medium
515 @SYMTestActions Tests for altering the table
516 @SYMTestExpectedResults Test must not fail
519 LOCAL_C void TestFullTableL()
521 test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0576 Create database "));
524 test.Next(_L("Add non-null column"));
526 CDbColSet* set=TableDefinitionL(KTableName);
527 TDbCol col10=TDbCol(TPtrC(KColumn10),EDbColInt32);
528 col10.iAttributes=TDbCol::ENotNull;
530 test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
532 test.Next(_L("Add nullable column"));
533 set->Remove(col10.iName);
536 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
539 test.Next(_L("Drop columns one by one"));
540 while (set->Count()>1)
542 set->Remove((*set)[1].iName);
543 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
547 test(TheDatabase.DropTable(KTableName)==KErrNone);
549 test.Next(_L("Extend a text column"));
550 BuildTableL(Set::Extended);
551 set=Set::CreateL(Set::LongerText);
552 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
556 test.Next(_L("Extend it to a LongText column"));
557 set=Set::CreateL(Set::TextToLongText);
558 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
562 test.Next(_L("Drop all except one"));
563 set=Set::CreateL(Set::Column3);
564 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
567 test(TheDatabase.DropTable(KTableName)==KErrNone);
568 test.Next(_L("Drop single column"));
569 for (TInt ii=EBit;ii<=EExtra;++ii)
571 BuildTableL(Set::Extended);
572 CDbColSet* set=TableDefinitionL(KTableName);
573 set->Remove(KColumns[ii]);
574 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
577 test(TheDatabase.DropTable(KTableName)==KErrNone);
579 test.Next(_L("Drop multiple columns"));
581 set=Set::CreateL(Set::DropSome);
582 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
585 test.Next(_L("Drop and add together"));
586 set=Set::CreateL(Set::DropAndAdd);
587 test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
590 test(TheDatabase.DropTable(KTableName)==KErrNone);
599 test.Start(_L("Alter empty table"));
600 TRAPD(r,TestEmptyTableL();)
603 test.Next(_L("Alter full table"));
604 TRAP(r,TestFullTableL();)
612 // Prepare the test directory.
614 LOCAL_C void setupTestDirectory()
616 TInt r=TheFs.Connect();
619 r=TheFs.MkDir(KTestDir);
620 test(r==KErrNone || r==KErrAlreadyExists);
621 r=TheFs.SetSessionPath(KTestDir);
626 // Initialise the cleanup stack.
628 LOCAL_C void setupCleanup()
630 TheTrapCleanup=CTrapCleanup::New();
631 test(TheTrapCleanup!=NULL);
634 for (TInt i=KTestCleanupStack;i>0;i--)\
635 CleanupStack::PushL((TAny*)0);\
636 CleanupStack::Pop(KTestCleanupStack);\
641 LOCAL_C void DeleteDataFile(const TDesC& aFullName)
644 TInt err = fsSession.Connect();
648 if(fsSession.Entry(aFullName, entry) == KErrNone)
650 RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
651 err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
654 RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
656 err = fsSession.Delete(aFullName);
659 RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
666 RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
671 // Test streaming conversions.
673 GLDEF_C TInt E32Main()
676 setupTestDirectory();
680 test.Start(_L("Standard database"));
682 test.Next(_L("Secure database"));
685 // clean up data files used by this test - must be done before call to End() - DEF047652
686 _LIT(KTestDbName, "C:\\DBMS-TST\\T_ALTER.DB");
687 ::DeleteDataFile(KTestDbName);
692 delete TheTrapCleanup;