os/persistentdata/persistentstorage/dbms/tdbms/t_dbalter.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include <d32dbms.h>
    17 #include <s32file.h>
    18 #include <e32test.h>
    19 
    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;
    25 LOCAL_D RFs TheFs;
    26 
    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"));
    33 
    34 TInt KRecords=100;
    35 
    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));
    47 
    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[]=
    60 	{
    61 	KColumn1,
    62 	KColumn2,
    63 	KColumn3,
    64 	KColumn4,
    65 	KColumn5,
    66 	KColumn6,
    67 	KColumn7,
    68 	KColumn8,
    69 	KColumn9
    70 	};
    71 
    72 class Set
    73 	{
    74 public:
    75 	struct SColDef
    76 		{
    77 		const TText* iName;
    78 		TDbColType iType;
    79 		TInt iAttributes;
    80 		TInt iMaxLength;
    81 		};
    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[];
    94 public:
    95 	static CDbColSet* CreateL(const SColDef* aDef);
    96 	};
    97 // the basic column definition
    98 enum TCol {EBit,EInt,EText,ELong,EBitNull,EIntNull,ETextNull,ELongNull,EExtra};
    99 Set::SColDef const Set::Basic[]=
   100 	{
   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},
   109 	{0}
   110 	};
   111 // a basically invalid set
   112 Set::SColDef const Set::Bad[]=
   113 	{
   114 	{KColumn9,EDbColInt32,0,-1},
   115 	{KColumn9,EDbColInt32,0,-1},
   116 	{0}
   117 	};
   118 // an incompatible set with Basic
   119 Set::SColDef const Set::Incompatible1[]=
   120 	{
   121 	{KColumn1,EDbColInt32,TDbCol::ENotNull,-1},	// retype a column
   122 	{0}
   123 	};
   124 Set::SColDef const Set::Incompatible2[]=
   125 	{
   126 	{KColumn5,EDbColBit,TDbCol::ENotNull,-1},	// change attributes
   127 	{0}
   128 	};
   129 Set::SColDef const Set::Incompatible3[]=
   130 	{
   131 	{KColumn8,EDbColText,0,49},	// shrink a text column
   132 	{0}
   133 	};
   134 // a wildly different set
   135 Set::SColDef const Set::Different[]=
   136 	{
   137 	{KColumn11,EDbColInt32,0,-1},
   138 	{KColumn4,EDbColLongBinary,TDbCol::ENotNull,-1},
   139 	{KColumn10,EDbColBit,TDbCol::ENotNull,-1},
   140 	{KColumn3,EDbColText,TDbCol::ENotNull,-1},
   141 	{0}
   142 	};
   143 // basic + 1 column
   144 Set::SColDef const Set::Extended[]=
   145 	{
   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
   155 	{0}
   156 	};
   157 // Extended with a longer text column
   158 Set::SColDef const Set::LongerText[]=
   159 	{
   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},
   169 	{0}
   170 	};
   171 // Extended with a text->LongText column
   172 Set::SColDef const Set::TextToLongText[]=
   173 	{
   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},
   183 	{0}
   184 	};
   185 Set::SColDef const Set::Column3[]=
   186 	{
   187 	{KColumn3,EDbColText,TDbCol::ENotNull,-1},
   188 	{0}
   189 	};
   190 Set::SColDef const Set::DropSome[]=
   191 	{
   192 	{KColumn1,EDbColBit,TDbCol::ENotNull,-1},
   193 	{KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
   194 	{KColumn6,EDbColInt32,0,-1},
   195 	{KColumn7,EDbColText,0,-1},
   196 	{0}
   197 	};
   198 Set::SColDef const Set::DropAndAdd[]=
   199 	{
   200 	{KColumn2,EDbColInt32,TDbCol::ENotNull,-1},
   201 	{KColumn7,EDbColText,0,-1},
   202 	{KColumn10,EDbColBinary,0,-1},
   203 	{0}
   204 	};
   205 
   206 CDbColSet* Set::CreateL(const SColDef* aDef)
   207 	{
   208 	CDbColSet *set=CDbColSet::NewLC();
   209 	for (;aDef->iName;++aDef)
   210 		{
   211 		TDbCol col(TPtrC(aDef->iName),aDef->iType);
   212 		col.iAttributes=aDef->iAttributes;
   213 		if (aDef->iMaxLength>=0)
   214 			col.iMaxLength=aDef->iMaxLength;
   215 		set->AddL(col);
   216 		}
   217 	CleanupStack::Pop();
   218 	return set;
   219 	}
   220 
   221 //
   222 // Create the database-in-a-store
   223 //
   224 LOCAL_C void CreateDatabaseL()
   225 	{
   226 	CFileStore* store=CPermanentFileStore::ReplaceLC(TheFs,KTestFile,EFileRead|EFileWrite);
   227 	store->SetTypeL(KPermanentFileStoreLayoutUid);
   228 	TStreamId id;
   229 	    id=TheDatabase.CreateL(store);
   230 	store->SetRootL(id);
   231 	store->CommitL();
   232 	CleanupStack::Pop();
   233 	TheStore=store;
   234 	}
   235 
   236 //
   237 // Open the database-in-a-store
   238 //
   239 LOCAL_C void OpenDatabaseL()
   240 	{
   241 	CFileStore* store=CFileStore::OpenLC(TheFs,KTestFile,EFileRead|EFileWrite);
   242 	TStreamId id=store->Root();
   243 	    TheDatabase.OpenL(store,id);
   244 	CleanupStack::Pop();
   245 	TheStore=store;
   246 	}
   247 
   248 LOCAL_C void CloseDatabaseL()
   249 	{
   250 	TheDatabase.Close();
   251 	delete TheStore;
   252 	}
   253 
   254 LOCAL_C void DestroyDatabaseL()
   255 	{
   256 	TheDatabase.Destroy();
   257 	TheStore->CommitL();
   258 	delete TheStore;
   259 	}
   260 
   261 LOCAL_C CDbColSet* TableDefinitionL(const TDesC& aTable)
   262 	{
   263 	RDbTable table;
   264 	test(table.Open(TheDatabase,aTable,table.EReadOnly)==KErrNone);
   265 	CDbColSet* cs=table.ColSetL();
   266 	table.Close();
   267 	return cs;
   268 	}
   269 
   270 //
   271 // Compare two column sets
   272 //
   273 LOCAL_C void Compare(const CDbColSet& aLeft,const CDbColSet& aRight)
   274 	{
   275 	test(aLeft.Count()==aRight.Count());
   276 	for (TDbColSetIter iter(aLeft);iter;++iter)
   277 		{
   278 		const TDbCol* pRight=aRight.Col(iter->iName);
   279 		test(pRight!=NULL);
   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);
   283 		}
   284 	}
   285 
   286 /**
   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
   293 @SYMREQ                 REQ0000
   294 */
   295 LOCAL_C void TestEmptyTableL()
   296 	{
   297 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0575 Create table "));
   298 	CreateDatabaseL();
   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);
   303 	delete set;
   304 //
   305 	test.Next(_L("Alter to bad definitions"));
   306 	set=Set::CreateL(Set::Bad);
   307 	test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
   308 	delete set;
   309 	set=Set::CreateL(Set::Incompatible1);
   310 	test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
   311 	delete set;
   312 	set=Set::CreateL(Set::Incompatible2);
   313 	test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
   314 	delete set;
   315 	set=Set::CreateL(Set::Incompatible3);
   316 	test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
   317 	delete set;
   318 //
   319 	test.Next(_L("Drop an indexed column"));
   320 	CDbKey* key=CDbKey::NewLC();
   321 	key->AddL(TPtrC(KColumn2));
   322 	key->MakeUnique();
   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);
   329 	delete set;
   330 //
   331 	test.Next(_L("Extend an indexed text column"));
   332 	set=Set::CreateL(Set::Extended);
   333 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   334 	delete set;
   335 	key=CDbKey::NewLC();
   336 	key->AddL(TPtrC(KColumn8));
   337 	key->MakeUnique();
   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);
   343 //
   344 	test.Next(_L("Extend a text column"));
   345 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   346 	delete set;
   347 //
   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);
   351 	delete set;
   352 //
   353 	test.Next(_L("Alter to a very different set"));
   354 	set=Set::CreateL(Set::Different);
   355 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   356 	CloseDatabaseL();
   357 	OpenDatabaseL();
   358 	CDbColSet* def=TableDefinitionL(KTableName);
   359 	Compare(*set,*def);
   360 	delete def;
   361 	delete set;
   362 	test.End();
   363 	test(TheDatabase.DropTable(KTableName)==KErrNone);
   364 	DestroyDatabaseL();
   365 	}
   366 
   367 class Map
   368 	{
   369 public:
   370 	Map();
   371 	void Init(RDbRowSet& aSet);
   372 	inline TDbColNo operator[](TInt aCol) const
   373 		{return iMap[aCol];}
   374 private:
   375 	TDbColNo iMap[EExtra+1];
   376 	};
   377 
   378 Map::Map()
   379 	{
   380 	}
   381 
   382 void Map::Init(RDbRowSet& aSet)
   383 	{
   384 	CDbColSet* set=NULL;
   385 	TRAPD(errCode, set=aSet.ColSetL());
   386 	if(errCode != KErrNone)
   387 		{
   388 		return;
   389 		}
   390 	for (TInt ii=EBit;ii<=EExtra;++ii)
   391 		iMap[ii]=set->ColNo(KColumns[ii]);
   392 	if(set)
   393 		delete set;
   394 	}
   395 
   396 //
   397 // Build the table for Altering
   398 //
   399 LOCAL_C void BuildTableL(const Set::SColDef* aDef=Set::Basic)
   400 	{
   401 	CDbColSet* set=Set::CreateL(aDef);
   402 	test(TheDatabase.CreateTable(KTableName,*set)==KErrNone);
   403 	delete set;
   404 	TheDatabase.Begin();
   405 	test(TheTable.Open(TheDatabase,KTableName,TheTable.EInsertOnly)==KErrNone);
   406 	Map map;
   407 	map.Init(TheTable);
   408 	for (TInt ii=0;ii<KRecords;++ii)
   409 		{
   410 		TheTable.InsertL();
   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);
   425 		TheTable.PutL();
   426 		}
   427 	TheTable.Close();
   428 	test(TheDatabase.Commit()==KErrNone);
   429 	}
   430 
   431 LOCAL_C void CheckBlobL(TDbColNo aCol,const TDesC8& aData)
   432 	{
   433 	test(TheTable.ColSize(aCol)==aData.Size());
   434 	TBuf8<500> buf;
   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();
   440 	test(buf==aData);
   441 	}
   442 
   443 #if defined(UNICODE)
   444 LOCAL_C void CheckBlobL(TDbColNo aCol,const TDesC16& aData)
   445 	{
   446 	test(TheTable.ColSize(aCol)==aData.Size());
   447 	TBuf16<500> buf;
   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();
   453 	test(buf==aData);
   454 	}
   455 #endif
   456 
   457 //
   458 // Check that the columns which still exist, still contain the same stuff
   459 // New columns should be Null
   460 //
   461 LOCAL_C void CheckTableL()
   462 	{
   463 	test(TheTable.Open(TheDatabase,KTableName,TheTable.EReadOnly)==KErrNone);
   464 	Map map;
   465 	map.Init(TheTable);
   466 
   467 	for (TInt ii=0;ii<KRecords;++ii)
   468 		{
   469 		test(TheTable.NextL());
   470 		TheTable.GetL();
   471 		if (map[EBit])
   472 			test(TheTable.ColUint(map[EBit])==KCol1Data);
   473 		if (map[EInt])
   474 			test(TheTable.ColInt(map[EInt])==KCol2Data);
   475 		if (map[EText])
   476 			test(TheTable.ColDes(map[EText])==KCol3Data);
   477 		if (map[ELong])
   478 			CheckBlobL(map[ELong],KCol4Data);
   479 		for (TInt jj=EBitNull;jj<=EExtra;++jj)
   480 			{
   481 			if (!map[jj])
   482 				continue;
   483 			if (ii%jj)
   484 				test(TheTable.IsColNull(map[jj]));
   485 			else
   486 				{
   487 				switch (jj)
   488 					{
   489 				case EBitNull:
   490 					test(TheTable.ColUint(map[EBitNull])==KCol5Data);
   491 					break;
   492 				case EIntNull:
   493 					test(TheTable.ColInt(map[EIntNull])==KCol6Data);
   494 					break;
   495 				case ETextNull:
   496 					test(TheTable.ColDes(map[ETextNull])==KCol7Data);
   497 					break;
   498 				case ELongNull:
   499 					CheckBlobL(map[ELongNull],KCol8Data);
   500 					break;
   501 				case EExtra:
   502 					CheckBlobL(map[EExtra],KCol9Data);
   503 					break;
   504 					}
   505 				}
   506 			}
   507 		}
   508 	TheTable.Close();
   509 	}
   510 
   511 /**
   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
   517 @SYMREQ                 REQ0000
   518 */
   519 LOCAL_C void TestFullTableL()
   520 	{
   521 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0576 Create database "));
   522 	CreateDatabaseL();
   523 //
   524 	test.Next(_L("Add non-null column"));
   525 	BuildTableL();
   526 	CDbColSet* set=TableDefinitionL(KTableName);
   527 	TDbCol col10=TDbCol(TPtrC(KColumn10),EDbColInt32);
   528 	col10.iAttributes=TDbCol::ENotNull;
   529 	set->AddL(col10);
   530 	test(TheDatabase.AlterTable(KTableName,*set)!=KErrNone);
   531 //
   532 	test.Next(_L("Add nullable column"));
   533 	set->Remove(col10.iName);
   534 	col10.iAttributes=0;
   535 	set->AddL(col10);
   536 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   537 	CheckTableL();
   538 //
   539 	test.Next(_L("Drop columns one by one"));
   540 	while (set->Count()>1)
   541 		{
   542 		set->Remove((*set)[1].iName);
   543 		test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   544 		CheckTableL();
   545 		}
   546 	delete set;
   547 	test(TheDatabase.DropTable(KTableName)==KErrNone);
   548 //
   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);
   553 	delete set;
   554 	CheckTableL();
   555 //
   556 	test.Next(_L("Extend it to a LongText column"));
   557 	set=Set::CreateL(Set::TextToLongText);
   558 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   559 	delete set;
   560 	CheckTableL();
   561 //
   562 	test.Next(_L("Drop all except one"));
   563 	set=Set::CreateL(Set::Column3);
   564 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   565 	delete set;
   566 	CheckTableL();
   567 	test(TheDatabase.DropTable(KTableName)==KErrNone);
   568 	test.Next(_L("Drop single column"));
   569 	for (TInt ii=EBit;ii<=EExtra;++ii)
   570 		{
   571 		BuildTableL(Set::Extended);
   572 		CDbColSet* set=TableDefinitionL(KTableName);
   573 		set->Remove(KColumns[ii]);
   574 		test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   575 		delete set;
   576 		CheckTableL();
   577 		test(TheDatabase.DropTable(KTableName)==KErrNone);
   578 		}
   579 	test.Next(_L("Drop multiple columns"));
   580 	BuildTableL();
   581 	set=Set::CreateL(Set::DropSome);
   582 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   583 	delete set;
   584 	CheckTableL();
   585 	test.Next(_L("Drop and add together"));
   586 	set=Set::CreateL(Set::DropAndAdd);
   587 	test(TheDatabase.AlterTable(KTableName,*set)==KErrNone);
   588 	delete set;
   589 	CheckTableL();
   590 	test(TheDatabase.DropTable(KTableName)==KErrNone);
   591 	test.End();
   592 	DestroyDatabaseL();
   593 	}
   594 
   595 LOCAL_C void Test()
   596 	{
   597 	__UHEAP_MARK;
   598 //
   599 	test.Start(_L("Alter empty table"));
   600 	TRAPD(r,TestEmptyTableL();)
   601 	test(r==KErrNone);
   602 	__UHEAP_CHECK(0);
   603 	test.Next(_L("Alter full table"));
   604 	TRAP(r,TestFullTableL();)
   605 	test(r==KErrNone);
   606 	test.End();
   607 //
   608 	__UHEAP_MARKEND;
   609 	}
   610 
   611 //
   612 // Prepare the test directory.
   613 //
   614 LOCAL_C void setupTestDirectory()
   615     {
   616 	TInt r=TheFs.Connect();
   617 	test(r==KErrNone);
   618 //
   619 	r=TheFs.MkDir(KTestDir);
   620 	test(r==KErrNone || r==KErrAlreadyExists);
   621 	r=TheFs.SetSessionPath(KTestDir);
   622 	test(r==KErrNone);
   623 	}
   624 
   625 //
   626 // Initialise the cleanup stack.
   627 //
   628 LOCAL_C void setupCleanup()
   629     {
   630 	TheTrapCleanup=CTrapCleanup::New();
   631 	test(TheTrapCleanup!=NULL);
   632 	TRAPD(r,\
   633 		{\
   634 		for (TInt i=KTestCleanupStack;i>0;i--)\
   635 			CleanupStack::PushL((TAny*)0);\
   636 		CleanupStack::Pop(KTestCleanupStack);\
   637 		});
   638 	test(r==KErrNone);
   639 	}
   640 
   641 LOCAL_C void DeleteDataFile(const TDesC& aFullName)
   642 	{
   643 	RFs fsSession;
   644 	TInt err = fsSession.Connect();
   645 	if(err == KErrNone)
   646 		{
   647 		TEntry entry;
   648 		if(fsSession.Entry(aFullName, entry) == KErrNone)
   649 			{
   650 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
   651 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
   652 			if(err != KErrNone)
   653 				{
   654 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
   655 				}
   656 			err = fsSession.Delete(aFullName);
   657 			if(err != KErrNone)
   658 				{
   659 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
   660 				}
   661 			}
   662 		fsSession.Close();
   663 		}
   664 	else
   665 		{
   666 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
   667 		}
   668 	}
   669 
   670 //
   671 // Test streaming conversions.
   672 //
   673 GLDEF_C TInt E32Main()
   674     {
   675 	test.Title();
   676 	setupTestDirectory();
   677 	setupCleanup();
   678 	__UHEAP_MARK;
   679 //
   680 	test.Start(_L("Standard database"));
   681 	Test();
   682 	test.Next(_L("Secure database"));
   683 	Test();
   684 
   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);
   688 
   689 	test.End();
   690 //
   691 	__UHEAP_MARKEND;
   692 	delete TheTrapCleanup;
   693 
   694 	TheFs.Close();
   695 	test.Close();
   696 	return 0;
   697     }