persistentstorage/sql/TEST/t_sqlblob.cpp
changeset 0 08ec8eefde2f
child 12 6b6fd149daa2
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-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 <e32test.h>
       
    17 #include <bautils.h>
       
    18 #include <sqldb.h>
       
    19 #include <s32file.h>
       
    20 
       
    21 RTest TheTest(_L("t_sqlblob test"));
       
    22 
       
    23 RSqlDatabase TheDb1;
       
    24 RSqlDatabase TheDb2;
       
    25 RSqlDatabase ThePrivateDb;
       
    26 
       
    27 _LIT(KTestDir, "c:\\test\\");
       
    28 _LIT(KTestDbName1, "c:\\test\\t_blob1.db");
       
    29 _LIT(KTestDbName2, "c:\\test\\t_blob2.db");
       
    30 _LIT(KAttachedDbName, "attached_db");
       
    31 _LIT(KPrivateSecureDb, "c:\\private\\1111C1CC\\ps.db"); 
       
    32 
       
    33 const TInt KLargeDataBufLen = 2048;
       
    34 
       
    35 // A buffer containing 2Kb of data.
       
    36 // When it is used to write to a blob the data will exceed the size of the client buffer
       
    37 // (which is 8 bytes in debug, 1.5Kb on target) and will be immediately transferred to the server
       
    38 TBuf8<KLargeDataBufLen> TheLargeData;
       
    39 
       
    40 ///////////////////////////////////////////////////////////////////////////////////////
       
    41 // Test database delete functions
       
    42 
       
    43 void DeleteTestDbs()
       
    44 	{
       
    45 	TheDb1.Close();
       
    46 	TheDb2.Close();
       
    47 	ThePrivateDb.Close();
       
    48 	(void)RSqlDatabase::Delete(KTestDbName1);
       
    49 	(void)RSqlDatabase::Delete(KTestDbName2);
       
    50 	(void)RSqlDatabase::Delete(KPrivateSecureDb);
       
    51 	}
       
    52 
       
    53 ///////////////////////////////////////////////////////////////////////////////////////
       
    54 // Test macros and functions
       
    55 
       
    56 void Check(TInt aValue, TInt aLine)
       
    57 	{
       
    58 	if(!aValue)
       
    59 		{
       
    60 		DeleteTestDbs();
       
    61 		TheTest(EFalse, aLine);
       
    62 		}
       
    63 	}
       
    64 void Check(TInt aValue, TInt aExpected, TInt aLine)
       
    65 	{
       
    66 	if(aValue != aExpected)
       
    67 		{
       
    68 		DeleteTestDbs();
       
    69 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
    70 		TheTest(EFalse, aLine);
       
    71 		}
       
    72 	}
       
    73 #define TEST(arg) ::Check((arg), __LINE__)
       
    74 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
    75 
       
    76 ///////////////////////////////////////////////////////////////////////////////////////
       
    77 // Test database create functions
       
    78 
       
    79 void CreateTestDir()
       
    80     {
       
    81     RFs fs;
       
    82 	TInt err = fs.Connect();
       
    83 	TEST2(err, KErrNone);
       
    84 
       
    85 	err = fs.MkDir(KTestDir);
       
    86 	TEST(err == KErrNone || err == KErrAlreadyExists);
       
    87 
       
    88 	err = fs.CreatePrivatePath(EDriveC);	
       
    89 	TEST(err == KErrNone || err == KErrAlreadyExists);
       
    90 	
       
    91 	fs.Close();
       
    92 	}
       
    93 
       
    94 void CreateTestDbs()
       
    95 	{
       
    96 	// Create t_blob1.db
       
    97 	TInt err = TheDb1.Create(KTestDbName1);
       
    98 	TEST2(err, KErrNone);
       
    99 	
       
   100  	err = TheDb1.Exec(_L("CREATE TABLE table1(I INTEGER, T TEXT, B BLOB)"));	
       
   101 	TEST(err >= 0);	
       
   102 	
       
   103 	// Create t_blob2.db
       
   104 	err = TheDb2.Create(KTestDbName2);
       
   105 	TEST2(err, KErrNone);
       
   106 
       
   107 	err = TheDb2.Exec(_L("CREATE TABLE table2(int INTEGER, text TEXT, blob BLOB)"));	
       
   108 	TEST(err >= 0);
       
   109 		
       
   110 	// Insert a blob value of 'FGFGFGFGFG' (10 characters in size)		
       
   111 	err = TheDb2.Exec(_L("INSERT INTO table2 VALUES(1, 'Text Data', x'46474647464746474647')"));
       
   112 	TEST2(err, 1);	
       
   113 	
       
   114 	// Create private secure db
       
   115 	err = ThePrivateDb.Create(KPrivateSecureDb);
       
   116 	TEST2(err, KErrNone);
       
   117 	
       
   118 	err = ThePrivateDb.Exec(_L("CREATE TABLE table3(age INTEGER, name TEXT, picture BLOB)"));	
       
   119 	TEST(err >= 0);
       
   120 	
       
   121 	// Insert a blob value of 'ABABABABABABABA' (15 characters in size)		
       
   122 	err = ThePrivateDb.Exec(_L("INSERT INTO table3 VALUES(31, 'John Smith', x'414241424142414241424142414241')"));
       
   123 	TEST2(err, 1);		
       
   124 	}
       
   125 	
       
   126 void CreateIndices()
       
   127 	{
       
   128 	TInt err = TheDb1.Exec(_L("CREATE INDEX textIdx1 on table1(T)"));	
       
   129 	TEST(err >= 0);
       
   130 	err = TheDb1.Exec(_L("CREATE INDEX blobIdx1 on table1(B)"));	
       
   131 	TEST(err >= 0);
       
   132 	
       
   133 	err = TheDb2.Exec(_L("CREATE INDEX textIdx2 on table2(text)"));	
       
   134 	TEST(err >= 0);
       
   135 	err = TheDb2.Exec(_L("CREATE INDEX blobIdx2 on table2(blob)"));	
       
   136 	TEST(err >= 0);
       
   137 	}
       
   138 	
       
   139 void RemoveIndices()
       
   140 	{
       
   141 	TInt err = TheDb1.Exec(_L("DROP INDEX textIdx1"));	
       
   142 	TEST(err >= 0);
       
   143 	err = TheDb1.Exec(_L("DROP INDEX blobIdx1"));	
       
   144 	TEST(err >= 0);
       
   145 
       
   146 	err = TheDb2.Exec(_L("DROP INDEX textIdx2"));	
       
   147 	TEST(err >= 0);
       
   148 	err = TheDb2.Exec(_L("DROP INDEX blobIdx2"));	
       
   149 	TEST(err >= 0);
       
   150 	}
       
   151 		
       
   152 void AttachTestDb2()
       
   153 	{
       
   154 	TInt err = TheDb1.Attach(KTestDbName2, KAttachedDbName);
       
   155 	TEST2(err, KErrNone);
       
   156 	}
       
   157 	
       
   158 void FillLargeDataBuf(TChar aChar = 'Z')
       
   159 	{
       
   160 	TheLargeData.Fill(aChar, KLargeDataBufLen);	
       
   161 	}
       
   162 	
       
   163 ///////////////////////////////////////////////////////////////////////////////////////
       
   164 // Unit test functions
       
   165 
       
   166 void CheckBlobPropertiesL(TInt aBlobSize)
       
   167 	{
       
   168 	// Check properties of the last inserted blob 
       
   169 		
       
   170 	RSqlStatement stmt;
       
   171 	CleanupClosePushL(stmt);
       
   172 	TInt err = stmt.Prepare(TheDb1, _L("SELECT B FROM table1 WHERE ROWID == :Val"));
       
   173 	TEST2(err, KErrNone);
       
   174 	TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
       
   175 	TEST(paramIndex >= 0);	
       
   176 	err = stmt.BindInt(paramIndex, TheDb1.LastInsertedRowId());
       
   177 	TEST2(err, KErrNone);
       
   178 	err = stmt.Next();
       
   179 	TEST2(err, KSqlAtRow);
       
   180 	
       
   181 	// Check the 'declared column type' is ESqlBinary
       
   182 	TSqlColumnType declColType;
       
   183 	err = stmt.DeclaredColumnType(0, declColType);
       
   184 	TEST2(declColType, ESqlBinary);
       
   185 	// Check the 'runtime column type' is ESqlBinary
       
   186 	TSqlColumnType colType = stmt.ColumnType(0);
       
   187 	TEST2(colType, ESqlBinary);
       
   188 	// Check the 'column size' is the size of the blob
       
   189 	TInt blobSize = stmt.ColumnSize(0);
       
   190 	TEST2(blobSize, aBlobSize);
       
   191 	// Check the 'column value' is not 'NULL' (even for a zeroblob)
       
   192 	TBool isNull = stmt.IsNull(0);
       
   193 	TEST2(isNull, EFalse);
       
   194 	// Check the 'column value' can be retrieved as a binary value
       
   195 	TPtrC8 binaryPtr = stmt.ColumnBinaryL(0);
       
   196 	TEST2(binaryPtr.Length(), aBlobSize);
       
   197 	// Check the 'column value' cannot be retrieved as a text value (it is of type ESqlBinary)
       
   198 	TPtrC textptr = stmt.ColumnTextL(0);
       
   199 	TEST2(textptr.Length(), 0);	
       
   200 	CleanupStack::PopAndDestroy(&stmt);
       
   201 	}
       
   202 
       
   203 void InsertBindZeroBlob(TInt aBlobSize)
       
   204 	{
       
   205 	// Insert a record that has had a zeroblob bound to it
       
   206 	RSqlStatement stmt;
       
   207 	TInt err = stmt.Prepare(TheDb1, _L("INSERT INTO table1 values(1, 'some text', :Val)"));
       
   208 	TEST2(err, KErrNone);
       
   209 	TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
       
   210 	TEST(paramIndex >= 0);	
       
   211 	err = stmt.BindZeroBlob(paramIndex, aBlobSize);
       
   212 	TEST2(err, KErrNone);
       
   213 	err = stmt.Exec();
       
   214 	stmt.Close();
       
   215 	TEST2(err, 1);
       
   216 	}
       
   217 	
       
   218 void InsertSQLiteZeroBlob(TInt aBlobSize)
       
   219 	{		
       
   220 	// Insert a record that contains the 'zeroblob()' function
       
   221 	RSqlStatement stmt;
       
   222 	TInt err = stmt.Prepare(TheDb1, _L("INSERT INTO table1 values(2, 'more text', zeroblob(:Val))"));
       
   223 	TEST2(err, KErrNone);
       
   224 	TInt paramIndex = stmt.ParameterIndex(_L(":Val")); 
       
   225 	TEST(paramIndex >= 0);	
       
   226 	err = stmt.BindInt(paramIndex, aBlobSize);
       
   227 	TEST2(err, KErrNone);
       
   228 	err = stmt.Exec();
       
   229 	stmt.Close();
       
   230 	TEST2(err, 1);
       
   231 	}
       
   232 
       
   233 void InsertBlobValueL(TInt aBlobSize)
       
   234 	{	
       
   235 	// Insert a record that contains an actual blob value
       
   236 	HBufC8* binaryData = HBufC8::NewLC(aBlobSize);
       
   237 	TPtr8 binaryDataPtr(binaryData->Des());
       
   238 	for(TInt i = 0; i < aBlobSize/2; ++i)
       
   239 		{
       
   240 		binaryDataPtr.Append(_L8("DE"));
       
   241 		}
       
   242 		
       
   243 	RSqlStatement stmt;
       
   244 	CleanupClosePushL(stmt);
       
   245 	TInt err = stmt.Prepare(TheDb1, _L("INSERT INTO table1 values(3, 'even more text', :Val)"));
       
   246 	TEST2(err, KErrNone);
       
   247 	TInt paramIndex = stmt.ParameterIndex(_L(":Val")); 
       
   248 	TEST(paramIndex >= 0);	
       
   249 	err = stmt.BindBinary(paramIndex, binaryDataPtr);
       
   250 	TEST2(err, KErrNone);
       
   251 	err = stmt.Exec();
       
   252 	TEST2(err, 1);
       
   253 	CleanupStack::PopAndDestroy(2); // stmt, binaryData		
       
   254 	}	
       
   255 
       
   256 void StreamBlob1L(TInt aBlobSize) 
       
   257 	{	
       
   258 	// Blob 1 is a zeroblob of size aBlobSize
       
   259 	
       
   260 	// Read (zero) data from the blob
       
   261 	RSqlBlobReadStream rdStrm;
       
   262 	CleanupClosePushL(rdStrm);
       
   263 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   264 	TInt size = rdStrm.SizeL(); // check the blob's size
       
   265 	TEST2(size, aBlobSize); 
       
   266 	_LIT8(KFiveZeros, "\x0\x0\x0\x0\x0");
       
   267 	_LIT8(KTwentyZeros, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0");
       
   268 	TBuf8<50> data;
       
   269 	rdStrm.ReadL(data, 5);
       
   270 	TEST(data.Compare(KFiveZeros) == 0); // check 5 bytes of zero have been read
       
   271 	rdStrm.ReadL(data, 20);
       
   272 	TEST(data.Compare(KTwentyZeros) == 0);	// check 20 bytes of zero have been read
       
   273 	CleanupStack::PopAndDestroy(&rdStrm);
       
   274 	
       
   275 	// Write some actual data to the blob
       
   276 	RSqlBlobWriteStream wrStrm;
       
   277 	CleanupClosePushL(wrStrm);
       
   278 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   279 	size = wrStrm.SizeL(); // check the blob's size
       
   280 	TEST2(size, aBlobSize); 
       
   281 	wrStrm.WriteL(_L8("AABBCCDDEE")); // write 10 bytes
       
   282 	wrStrm.WriteL(_L8("FFGGHHIIJJ")); // write another 10 bytes
       
   283 	wrStrm.WriteL(_L8("KKLLMMNNOOPPQQRRSSTTUUVVWWXX")); // write another 28 bytes
       
   284 	wrStrm.CommitL();
       
   285 	CleanupStack::PopAndDestroy(&wrStrm);
       
   286 	
       
   287 	// Read back some of the blob data
       
   288 	CleanupClosePushL(rdStrm);
       
   289 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   290 	size = rdStrm.SizeL(); // check the blob's size
       
   291 	TEST2(size, aBlobSize);
       
   292 	rdStrm.ReadL(data, 4);
       
   293 	TEST(data.Compare(_L8("AABB")) == 0); // check the first 4 bytes
       
   294 	rdStrm.ReadL(data, 35);
       
   295 	TEST(data.Compare(_L8("CCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSST")) == 0); // check the next 35 bytes
       
   296 	rdStrm.ReadL(data, 19);
       
   297 	_LIT8(KTrailingZeros, "TUUVVWWXX\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"); 
       
   298 	TEST(data.Compare(KTrailingZeros) == 0); // check the next 19 bytes (which includes some of the original zero bytes)
       
   299 	CleanupStack::PopAndDestroy(&rdStrm);
       
   300 	}
       
   301 
       
   302 void StreamText1L() 
       
   303 	{	
       
   304 	// Read data from the text column -
       
   305 	// the database encoding is UTF-16 so the text is stored as UTF-16
       
   306 	RSqlBlobReadStream rdStrm;
       
   307 	CleanupClosePushL(rdStrm);
       
   308 	rdStrm.OpenL(TheDb1, _L("table1"), _L("T"));
       
   309 	TBuf<50> dataUTF16;
       
   310 	rdStrm.ReadL(dataUTF16, 9);
       
   311 	TEST(dataUTF16.Compare(_L("some text")) == 0); 
       
   312 	CleanupStack::PopAndDestroy(&rdStrm);
       
   313 	
       
   314 	// Write some data to the text column (as UTF-16)
       
   315 	RSqlBlobWriteStream wrStrm;
       
   316 	CleanupClosePushL(wrStrm);
       
   317 	wrStrm.OpenL(TheDb1, _L("table1"), _L("T"));
       
   318 	wrStrm.WriteL(_L("new text!")); // can only write up to the original size of the data - 9 chars
       
   319 	wrStrm.CommitL();
       
   320 	CleanupStack::PopAndDestroy(&wrStrm);
       
   321 	
       
   322 	// Read back some of the text (as UTF-16)
       
   323 	CleanupClosePushL(rdStrm);
       
   324 	rdStrm.OpenL(TheDb1, _L("table1"), _L("T"));
       
   325 	rdStrm.ReadL(dataUTF16, 9);
       
   326 	TEST(dataUTF16.Compare(_L("new text!")) == 0);
       
   327 	CleanupStack::PopAndDestroy(&rdStrm);
       
   328 	
       
   329 	// Write some data to the text column (as UTF-8)
       
   330 	CleanupClosePushL(wrStrm);
       
   331 	wrStrm.OpenL(TheDb1, _L("table1"), _L("T"));
       
   332 	wrStrm.WriteL(_L8("try again"));
       
   333 	wrStrm.CommitL();
       
   334 	CleanupStack::PopAndDestroy(&wrStrm);
       
   335 	
       
   336 	// Read back some of the text (as UTF-8)
       
   337 	CleanupClosePushL(rdStrm);
       
   338 	rdStrm.OpenL(TheDb1, _L("table1"), _L("T"));
       
   339 	TBuf8<50> dataUTF8;
       
   340 	rdStrm.ReadL(dataUTF8, 9);
       
   341 	TEST(dataUTF8.Compare(_L8("try again")) == 0);
       
   342 	CleanupStack::PopAndDestroy(&rdStrm);
       
   343 	}
       
   344 	
       
   345 void StreamBlob2L(TInt aBlobSize)
       
   346 	{
       
   347 	// Blob 2 is a zeroblob of size aBlobSize
       
   348 	
       
   349 	// Read (zero) data from the blob
       
   350 	RSqlBlobReadStream rdStrm;
       
   351 	CleanupClosePushL(rdStrm);
       
   352 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   353 	TInt size = rdStrm.SizeL(); // check the blob's size
       
   354 	TEST2(size, aBlobSize);
       
   355 	_LIT8(KFifteenZeros, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0");
       
   356 	_LIT8(KSixtyOneZeros, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0");
       
   357 	TBuf8<200> data;
       
   358 	rdStrm.ReadL(data, 15);
       
   359 	TEST(data.Compare(KFifteenZeros) == 0); // check 15 bytes of zero have been read
       
   360 	rdStrm.ReadL(data, 61);
       
   361 	TEST(data.Compare(KSixtyOneZeros) == 0); // check 61 bytes of zero have been read
       
   362 	size = rdStrm.SizeL(); // check the blob's size
       
   363 	TEST2(size, aBlobSize); 
       
   364 	CleanupStack::PopAndDestroy(&rdStrm); 
       
   365 
       
   366 	// Write some actual data to the blob 
       
   367 	RSqlBlobWriteStream wrStrm;
       
   368 	CleanupClosePushL(wrStrm);
       
   369 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   370 	size = wrStrm.SizeL(); // check the blob's size
       
   371 	TEST2(size, aBlobSize);
       
   372 	wrStrm.WriteL(_L8("SOMENEWDATASOMENEWDATAS")); // write 23 bytes
       
   373 	wrStrm.WriteL(_L8("OMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATA")); // write another 43 bytes
       
   374 	wrStrm.WriteL(_L8("SOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENE")); // write another 72 bytes
       
   375 	wrStrm.WriteL(_L8("WDATASOMENEWDATA")); // write another 16 bytes
       
   376 	size = wrStrm.SizeL(); // check the blob's size
       
   377 	TEST2(size, aBlobSize); 
       
   378 	wrStrm.CommitL();
       
   379 	CleanupStack::PopAndDestroy(&wrStrm); 
       
   380 	
       
   381 	// Read back some of the blob data
       
   382 	CleanupClosePushL(rdStrm);
       
   383 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   384 	size = rdStrm.SizeL(); // check the blob's size
       
   385 	TEST2(size, aBlobSize);
       
   386 	rdStrm.ReadL(data, 1);
       
   387 	TEST(data.Compare(_L8("S")) == 0);  // check the first byte
       
   388 	rdStrm.ReadL(data, 136);
       
   389 	TEST(data.Compare(_L8("OMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMENEWDATASOMEN")) == 0); // check the next 136 bytes
       
   390 	rdStrm.ReadL(data, 30);
       
   391 	_LIT8(KTrailingZeros, "EWDATASOMENEWDATA\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"); 
       
   392 	TEST(data.Compare(KTrailingZeros) == 0); // check the next 30 bytes (which includes some of the original zero bytes)
       
   393 	size = rdStrm.SizeL(); // check the blob's size
       
   394 	TEST2(size, aBlobSize); 
       
   395 	CleanupStack::PopAndDestroy(&rdStrm);	
       
   396 	}
       
   397 	
       
   398 void StreamBlob3L(TInt aBlobSize)
       
   399 	{
       
   400 	// Blob 3 is a 'real' blob of value "DEDEDEDEDEDEDEDEDEDE"
       
   401 	
       
   402 	// Read some of the zero data
       
   403 	RSqlBlobReadStream rdStrm;
       
   404 	CleanupClosePushL(rdStrm);
       
   405 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   406 	TInt size = rdStrm.SizeL(); // check the blob's size
       
   407 	TEST2(size, aBlobSize);
       
   408 	TBuf8<20> data;
       
   409 	rdStrm.ReadL(data, 3);
       
   410 	TEST(data.Compare(_L8("DED")) == 0); // check the first 3 bytes
       
   411 	rdStrm.ReadL(data, 12);
       
   412 	TEST(data.Compare(_L8("EDEDEDEDEDED")) == 0); // check the next 12 bytes
       
   413 	size = rdStrm.SizeL(); // check the blob's size
       
   414 	TEST2(size, aBlobSize); 
       
   415 	CleanupStack::PopAndDestroy(&rdStrm); 	
       
   416 	
       
   417 	// Write some new data to the blob 
       
   418 	RSqlBlobWriteStream wrStrm;
       
   419 	CleanupClosePushL(wrStrm);
       
   420 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   421 	size = wrStrm.SizeL(); // check the blob's size
       
   422 	TEST2(size, aBlobSize);
       
   423 	wrStrm.WriteL(_L8("ABCDEF")); // write 6 bytes
       
   424 	wrStrm.WriteL(_L8("GHIJKLMNOPQ")); // write another 11 bytes
       
   425 	size = wrStrm.SizeL(); // check the blob's size
       
   426 	TEST2(size, aBlobSize); 
       
   427 	wrStrm.CommitL();
       
   428 	CleanupStack::PopAndDestroy(&wrStrm);	
       
   429 	
       
   430 	// Read back some of the blob data
       
   431 	CleanupClosePushL(rdStrm);
       
   432 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   433 	size = rdStrm.SizeL(); // check the blob's size
       
   434 	TEST2(size, aBlobSize);
       
   435 	rdStrm.ReadL(data, 2);
       
   436 	TEST(data.Compare(_L8("AB")) == 0); // check the first 2 bytes
       
   437 	rdStrm.ReadL(data, 7);
       
   438 	TEST(data.Compare(_L8("CDEFGHI")) == 0); // check the next 7 bytes
       
   439 	rdStrm.ReadL(data, 11);
       
   440 	TEST(data.Compare(_L8("JKLMNOPQEDE")) == 0); // check the next 11 bytes
       
   441 	size = rdStrm.SizeL(); // check the blob's size
       
   442 	TEST2(size, aBlobSize); 
       
   443 	CleanupStack::PopAndDestroy(&rdStrm);	
       
   444 
       
   445 	// Seek to position - the blob value is now "ABCDEFGHIJKLMNOPQEDE"
       
   446 	CleanupClosePushL(rdStrm);
       
   447 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   448 	TStreamPos pos(9);
       
   449 	rdStrm.Source()->SeekL(MStreamBuf::ERead, pos);
       
   450 	rdStrm.ReadL(data, 2);
       
   451 	TEST(data.Compare(_L8("JK")) == 0);
       
   452 	rdStrm.ReadL(data, 5);
       
   453 	TEST(data.Compare(_L8("LMNOP")) == 0);
       
   454 	TStreamPos pos2(3);
       
   455 	rdStrm.Source()->SeekL(MStreamBuf::ERead, pos2);
       
   456 	rdStrm.ReadL(data, 4);
       
   457 	TEST(data.Compare(_L8("DEFG")) == 0);
       
   458 	TStreamPos pos3(21);
       
   459 	TRAPD(err, rdStrm.Source()->SeekL(MStreamBuf::ERead, pos3));
       
   460 	TEST2(err, KErrEof);
       
   461 	TStreamPos pos4(18);
       
   462 	rdStrm.Source()->SeekL(MStreamBuf::ERead, pos4);
       
   463 	TRAP(err, rdStrm.ReadL(data, 3));
       
   464 	TEST2(err, KErrEof);
       
   465 	CleanupStack::PopAndDestroy(&rdStrm);	
       
   466 
       
   467 	CleanupClosePushL(wrStrm);
       
   468 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   469 	TStreamPos pos5(7);
       
   470 	wrStrm.Sink()->SeekL(MStreamBuf::EWrite, pos5);
       
   471 	wrStrm.WriteL(_L8("ZZZZZ"));
       
   472 	wrStrm.WriteL(_L8("YYY"));
       
   473 	TStreamPos pos6(17);
       
   474 	wrStrm.Sink()->SeekL(MStreamBuf::EWrite, pos6);
       
   475 	wrStrm.WriteL(_L8("XXX"));
       
   476 	wrStrm.CommitL();
       
   477 	wrStrm.Close();
       
   478 	CleanupClosePushL(rdStrm);
       
   479 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   480 	rdStrm.ReadL(data, 20);
       
   481 	TEST(data.Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);
       
   482 	rdStrm.Close();
       
   483 	TStreamPos pos7(21);
       
   484 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   485 	TRAP(err, wrStrm.Sink()->SeekL(MStreamBuf::EWrite, pos7));
       
   486 	TEST2(err, KErrEof);
       
   487 	TStreamPos pos8(18);
       
   488 	wrStrm.Sink()->SeekL(MStreamBuf::EWrite, pos8);
       
   489 	wrStrm.WriteL(_L8("TTT"));
       
   490 	TRAP(err, wrStrm.CommitL());
       
   491 	TEST2(err, KErrEof);
       
   492 	wrStrm.Close();
       
   493 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   494 	rdStrm.ReadL(data, 20);
       
   495 	TEST(data.Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);
       
   496 	CleanupStack::PopAndDestroy(2);	
       
   497 	}
       
   498 	
       
   499 /**
       
   500 @SYMTestCaseID			SYSLIB-SQL-UT-4099
       
   501 @SYMTestCaseDesc		Incremental blob tests on a database using streams.
       
   502 						Insert a zeroblob using RSqlStatement::BindZeroBlob(), read and write to
       
   503 					 	the blob using streams, also read and write to a text column using streams.
       
   504 						Tests the RSqlBlobReadStream and RSqlBlobWriteStream methods.
       
   505 @SYMTestPriority		Medium
       
   506 @SYMTestActions			Execution of incremental blob stream operations on a database.
       
   507 @SYMTestExpectedResults Test must not fail
       
   508 @SYMREQ					REQ10411
       
   509                         REQ10418
       
   510 */	
       
   511 void StreamBindZeroBlobTestL()
       
   512 	{
       
   513 	const TInt KBlobSize = 300;
       
   514 	InsertBindZeroBlob(KBlobSize);
       
   515 	CheckBlobPropertiesL(KBlobSize);
       
   516 	StreamBlob1L(KBlobSize);
       
   517 	StreamText1L();
       
   518 	CheckBlobPropertiesL(KBlobSize);
       
   519 	}
       
   520 
       
   521 /**
       
   522 @SYMTestCaseID			SYSLIB-SQL-UT-4100
       
   523 @SYMTestCaseDesc		Incremental blob tests on a database, using streams.
       
   524 						Insert a zeroblob using the SQLite function zeroblob(), 
       
   525 						read and write to the blob using streams.
       
   526 						Tests the RSqlBlobReadStream and RSqlBlobWriteStream methods.
       
   527 @SYMTestPriority		Medium
       
   528 @SYMTestActions			Execution of incremental blob stream operations on a database.
       
   529 @SYMTestExpectedResults Test must not fail
       
   530 @SYMREQ					REQ10411
       
   531                         REQ10418
       
   532 */	
       
   533 void StreamSqliteZeroBlobTestL()
       
   534 	{
       
   535 	const TInt KBlobSize = 1500;
       
   536 	InsertSQLiteZeroBlob(KBlobSize);
       
   537 	CheckBlobPropertiesL(KBlobSize);
       
   538 	StreamBlob2L(KBlobSize);
       
   539 	CheckBlobPropertiesL(KBlobSize);
       
   540 	}
       
   541 
       
   542 /**
       
   543 @SYMTestCaseID			SYSLIB-SQL-UT-4101
       
   544 @SYMTestCaseDesc		Incremental blob tests on a database, using streams.
       
   545 						Insert a real blob, read and write to the blob using streams.
       
   546 						Tests the RSqlBlobReadStream and RSqlBlobWriteStream methods.
       
   547 @SYMTestPriority		Medium
       
   548 @SYMTestActions			Execution of incremental blob stream operations on a database.
       
   549 @SYMTestExpectedResults Test must not fail
       
   550 @SYMREQ					REQ10411
       
   551                         REQ10418
       
   552 */
       
   553 void StreamRealBlobTestL()
       
   554 	{
       
   555 	const TInt KBlobSize = 20;
       
   556 	InsertBlobValueL(KBlobSize);
       
   557 	CheckBlobPropertiesL(KBlobSize);
       
   558 	StreamBlob3L(KBlobSize);
       
   559 	CheckBlobPropertiesL(KBlobSize);
       
   560 	}
       
   561 	
       
   562 /**
       
   563 @SYMTestCaseID			SYSLIB-SQL-UT-4102
       
   564 @SYMTestCaseDesc		Whole value blob retrieval tests on a database.
       
   565 						Retrieve the whole value of a blob object in one go.
       
   566 						Tests the TSqlBlob 'get' methods.
       
   567 @SYMTestPriority		Medium
       
   568 @SYMTestActions			Execution of whole value blob retrieval operations on a database.
       
   569 @SYMTestExpectedResults Test must not fail
       
   570 @SYMREQ					REQ10411
       
   571                         REQ10418
       
   572 */
       
   573 void GetWholeBlob3L()
       
   574 	{
       
   575 	// Blob 3 is a 'real' blob of value "ABCDEFGZZZZZYYYPQXXX"
       
   576 	const TInt KBlobSize = 20;
       
   577 	
       
   578 	// Get the whole content of Blob 3 in one go, using TSqlBlob::GetLC()
       
   579 	HBufC8* wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"));
       
   580 	TInt bufSize = wholeBuf->Size();
       
   581 	TEST2(bufSize, KBlobSize);
       
   582 	TEST(wholeBuf->Des().Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);	
       
   583 	CleanupStack::PopAndDestroy(wholeBuf); 
       
   584 
       
   585 	// Get the whole content of Blob 3 in one go, using TSqlBlob::Get()
       
   586 	HBufC8* buf = HBufC8::NewLC(KBlobSize);	
       
   587 	TPtr8 bufPtr(buf->Des());	  
       
   588 	TInt err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr);
       
   589 	TEST2(err, KErrNone); 
       
   590 	TEST(bufPtr.Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);	
       
   591 	CleanupStack::PopAndDestroy(buf); 
       
   592 	
       
   593 	// Get the whole content of Blob 3 in one go, using TSqlBlob::Get(),
       
   594 	// ensuring that a buffer larger than the blob can be used
       
   595 	HBufC8* largerBuf = HBufC8::NewLC(KBlobSize * 2);	
       
   596 	TPtr8 largerBufPtr(largerBuf->Des());	  
       
   597 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), largerBufPtr);
       
   598 	TEST2(err, KErrNone); 
       
   599 	TEST(largerBufPtr.Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);	
       
   600 	CleanupStack::PopAndDestroy(largerBuf); 
       
   601 	
       
   602 	// Get the whole content of the blob in 2 chunks of 10 bytes
       
   603 	HBufC8* streamBuf = HBufC8::NewLC(10);
       
   604 	TPtr8 streamBufPtr(streamBuf->Des());
       
   605 	RSqlBlobReadStream rdStrm;
       
   606 	CleanupClosePushL(rdStrm);
       
   607 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   608 	TInt size = rdStrm.SizeL();
       
   609 	TEST2(size, KBlobSize);
       
   610 	HBufC8* combinedData = HBufC8::NewLC(KBlobSize);
       
   611 	TPtr8 combinedDataPtr(combinedData->Des());		
       
   612 	for(TInt i = 2; i > 0 ; --i)
       
   613 		{
       
   614 		rdStrm.ReadL(streamBufPtr, 10);
       
   615 		combinedDataPtr.Append(streamBufPtr);
       
   616 		}
       
   617 	TEST(combinedDataPtr.Compare(_L8("ABCDEFGZZZZZYYYPQXXX")) == 0);
       
   618 	CleanupStack::PopAndDestroy(3); // combinedDataRead, rdStrm, streamBuf
       
   619 	}
       
   620 
       
   621 /**
       
   622 @SYMTestCaseID			SYSLIB-SQL-UT-4104
       
   623 @SYMTestCaseDesc		Whole value blob write tests on a database.
       
   624 						Write the whole value of a blob object in one go.
       
   625 						Tests the TSqlBlob 'set' methods.
       
   626 @SYMTestPriority		Medium
       
   627 @SYMTestActions			Execution of whole value blob write operations on a database.
       
   628 @SYMTestExpectedResults Test must not fail
       
   629 @SYMREQ					REQ10411
       
   630                         REQ10418
       
   631 */
       
   632 void SetWholeBlob3L()
       
   633 	{
       
   634 	// Blob 3 is a 'real' blob of value "KKKKKKKKKKKKKKKKKEDE"
       
   635 	TInt KBlobSize = 20;
       
   636 	
       
   637 	// Set the whole content of Blob 3 in one go
       
   638 	HBufC8* dataBuf = HBufC8::NewLC(KBlobSize);
       
   639 	TPtr8 dataPtr(dataBuf->Des());
       
   640 	dataPtr.Append(_L8("CDCDCDCDCDCDCDCDCDCD"));
       
   641 	TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), dataPtr);
       
   642 	CleanupStack::PopAndDestroy(dataBuf); 
       
   643 	
       
   644 	// Check that the new blob data was written
       
   645 	HBufC8* retrievedDataBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"));
       
   646 	TInt blobLength = retrievedDataBuf->Size();
       
   647 	TEST2(blobLength, KBlobSize);
       
   648 	TEST(retrievedDataBuf->Des().Compare(_L8("CDCDCDCDCDCDCDCDCDCD")) == 0);		
       
   649 	CleanupStack::PopAndDestroy(retrievedDataBuf);
       
   650 	
       
   651 	// Set the whole content of the blob in 2 chunks of 10 bytes
       
   652 	RSqlBlobWriteStream wrStrm;
       
   653 	CleanupClosePushL(wrStrm);
       
   654 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   655 	TInt size = wrStrm.SizeL();
       
   656 	TEST2(size, KBlobSize);		
       
   657 	for(TInt i = 2; i > 0; --i)
       
   658 		{
       
   659 		wrStrm.WriteL(_L8("ZYZYZYZYZY")); 
       
   660 		}
       
   661 	CleanupStack::PopAndDestroy(&wrStrm);
       
   662 	
       
   663 	// Check that the new blob data was written
       
   664 	retrievedDataBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"));
       
   665 	blobLength = retrievedDataBuf->Size();
       
   666 	TEST2(blobLength, KBlobSize);
       
   667 	TEST(retrievedDataBuf->Des().Compare(_L8("ZYZYZYZYZYZYZYZYZYZY")) == 0);		
       
   668 	CleanupStack::PopAndDestroy(retrievedDataBuf);
       
   669 	}
       
   670 	
       
   671 /**
       
   672 @SYMTestCaseID			SYSLIB-SQL-UT-4106
       
   673 @SYMTestCaseDesc		Blob read and write tests on an attached database.
       
   674 						Performs streaming and whole value read and write operations
       
   675 						on a blob in an attached database to ensure that the 
       
   676 						RSqlBlobReadStream, RSqlBlobWriteStream and TSqlBlob methods 
       
   677 						can be used on an attached database.
       
   678 						Tests the RSqlBlobReadStream, RSqlBlobWriteStream and TSqlBlob methods.
       
   679 @SYMTestPriority		Medium
       
   680 @SYMTestActions			Execution of blob read and write operations on an attached database.
       
   681 @SYMTestExpectedResults Test must not fail
       
   682 @SYMREQ					REQ10411
       
   683                         REQ10418
       
   684 */
       
   685 void AttachDbTestL()
       
   686 	{
       
   687 	// Attach test db 2 to test db 1
       
   688 	AttachTestDb2();
       
   689 	
       
   690 	// Open a read stream on a blob in the attached database - 
       
   691 	// the blob in the single record has a value of "FGFGFGFGFG"
       
   692 	const TInt KAttachedBlobSize = 10;
       
   693 	RSqlBlobReadStream rdStrm;
       
   694 	CleanupClosePushL(rdStrm);
       
   695 	rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   696 	TInt size = rdStrm.SizeL(); // check the blob's size
       
   697 	TEST2(size, KAttachedBlobSize);
       
   698 	TBuf8<20> data;
       
   699 	rdStrm.ReadL(data, 2);
       
   700 	TEST(data.Compare(_L8("FG")) == 0);	// check the first 2 bytes
       
   701 	rdStrm.ReadL(data, 8);
       
   702 	TEST(data.Compare(_L8("FGFGFGFG")) == 0); // check the next 8 bytes
       
   703 	size = rdStrm.SizeL(); // check the blob's size
       
   704 	TEST2(size, KAttachedBlobSize); 
       
   705 	CleanupStack::PopAndDestroy(&rdStrm);	
       
   706 	
       
   707 	// Write some new data to the blob 
       
   708 	RSqlBlobWriteStream wrStrm;
       
   709 	CleanupClosePushL(wrStrm);
       
   710 	wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   711 	size = wrStrm.SizeL(); // check the blob's size
       
   712 	TEST2(size, KAttachedBlobSize);
       
   713 	wrStrm.WriteL(_L8("LLLL")); // write 4 bytes
       
   714 	wrStrm.WriteL(_L8("MMMMM")); // write another 5 bytes
       
   715 	size = wrStrm.SizeL(); // check the blob's size
       
   716 	TEST2(size, KAttachedBlobSize); 
       
   717 	wrStrm.CommitL();
       
   718 	CleanupStack::PopAndDestroy(&wrStrm);	
       
   719 	
       
   720 	// Read back some of the blob data
       
   721 	CleanupClosePushL(rdStrm);
       
   722 	rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   723 	size = rdStrm.SizeL(); // check the blob's size
       
   724 	TEST2(size, KAttachedBlobSize);
       
   725 	rdStrm.ReadL(data, 2);
       
   726 	TEST(data.Compare(_L8("LL")) == 0); // check the first 2 bytes
       
   727 	rdStrm.ReadL(data, 5);
       
   728 	TEST(data.Compare(_L8("LLMMM")) == 0); // check the next 5 bytes
       
   729 	rdStrm.ReadL(data, 3);
       
   730 	TEST(data.Compare(_L8("MMG")) == 0); // check the next 3 bytes
       
   731 	size = rdStrm.SizeL(); // check the blob's size
       
   732 	TEST2(size, KAttachedBlobSize); 
       
   733 	CleanupStack::PopAndDestroy(&rdStrm);	
       
   734 	
       
   735 	// Get the entire blob in the attached database
       
   736 	HBufC8* wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   737 	TInt blobLength = wholeBuf->Length();
       
   738 	TEST2(blobLength, KAttachedBlobSize);
       
   739 	TEST(wholeBuf->Des().Compare(_L8("LLLLMMMMMG")) == 0);	
       
   740 	CleanupStack::PopAndDestroy(wholeBuf); 
       
   741 		
       
   742 	TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), data, TheDb2.LastInsertedRowId(), KAttachedDbName);	 		 
       
   743 	TEST(data.Compare(_L8("LLLLMMMMMG")) == 0);	
       
   744 
       
   745 	// Set the entire blob in the attached database
       
   746 	data.Zero();
       
   747 	data.Append(_L8("STSTSTSTST"));
       
   748 	TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), data, TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   749 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName);
       
   750 	TEST(wholeBuf->Des().Compare(_L8("STSTSTSTST")) == 0);	
       
   751 	CleanupStack::PopAndDestroy(wholeBuf); 	
       
   752 	}	
       
   753 
       
   754 void BadParamReadStreamL()	
       
   755 	{
       
   756 	HBufC* tooLongName = HBufC::NewLC(KMaxFileName + 1);
       
   757 	TPtr tooLongNameDes = tooLongName->Des();
       
   758 	tooLongNameDes.Fill('A', KMaxFileName + 1);	
       
   759 
       
   760 	// RSqlBlobReadStream::OpenL()	
       
   761 	RSqlBlobReadStream rdStrm;
       
   762 	CleanupClosePushL(rdStrm);
       
   763 	TRAPD(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"))); // a successful open (on a BLOB column)
       
   764 	TEST2(err, KErrNone);
       
   765 	rdStrm.Close();
       
   766 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("T"))); // a successful open (on a TEXT column)
       
   767 	TEST2(err, KErrNone);
       
   768 	rdStrm.Close();
       
   769 	TRAP(err, rdStrm.OpenL(TheDb2, _L("table1"), _L("B"))); // wrong db connection
       
   770 	TEST2(err, KSqlErrGeneral); 
       
   771 	TRAP(err, rdStrm.OpenL(TheDb1, _L(""), _L("B"))); // empty table name
       
   772 	TEST2(err, KErrBadName);
       
   773 	TRAP(err, rdStrm.OpenL(TheDb1, tooLongNameDes, _L("B"))); // too long table name
       
   774 	TEST2(err, KErrBadName);
       
   775 	TRAP(err, rdStrm.OpenL(TheDb1, _L("invalidTableName"), _L("B"))); // invalid table name
       
   776 	TEST2(err, KSqlErrGeneral);
       
   777 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L(""))); // empty column name
       
   778 	TEST2(err, KErrBadName);
       
   779 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), tooLongNameDes)); // too long column name
       
   780 	TEST2(err, KErrBadName);
       
   781 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("invalidColumnName"))); // invalid column name
       
   782 	TEST2(err, KSqlErrGeneral);
       
   783 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("I"))); // invalid column type
       
   784 	TEST2(err, KSqlErrGeneral);
       
   785 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), -12)); // illegal ROWID
       
   786 	TEST2(err, KErrArgument);
       
   787 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), 99)); // invalid ROWID
       
   788 	TEST2(err, KSqlErrGeneral);
       
   789 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), KSqlLastInsertedRowId, _L("main"))); // a successful open (on a BLOB column)
       
   790 	TEST2(err, KErrNone);
       
   791 	rdStrm.Close();
       
   792 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), KSqlLastInsertedRowId, _L(""))); // a successful open (on a BLOB column)
       
   793 	TEST2(err, KErrNone);
       
   794 	rdStrm.Close();
       
   795 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("T"), KSqlLastInsertedRowId, _L("main"))); // a successful open (on a TEXT column)
       
   796 	TEST2(err, KErrNone);
       
   797 	rdStrm.Close();
       
   798 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("T"), KSqlLastInsertedRowId, _L(""))); // a successful open (on a TEXT column)
       
   799 	TEST2(err, KErrNone);
       
   800 	rdStrm.Close();
       
   801 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on a BLOB column)
       
   802 	TEST2(err, KErrNone);
       
   803 	rdStrm.Close();
       
   804 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on a TEXT column)
       
   805 	TEST2(err, KErrNone);
       
   806 	rdStrm.Close();
       
   807 	TRAP(err, rdStrm.OpenL(TheDb2, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // wrong db connection
       
   808 	TEST2(err, KSqlErrGeneral);
       
   809 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), tooLongNameDes)); // too long attached db name
       
   810 	TEST2(err, KErrBadName);
       
   811 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), _L("invalidAttachedDbName"))); // invalid attached db name
       
   812 	TEST2(err, KSqlErrGeneral);
       
   813 	TRAP(err, rdStrm.OpenL(TheDb1, _L("invalidTableName"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid table name
       
   814 	TEST2(err, KSqlErrGeneral);
       
   815 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("invalidColumnName"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column name
       
   816 	TEST2(err, KSqlErrGeneral);
       
   817 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("int"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column type
       
   818 	TEST2(err, KSqlErrGeneral);
       
   819 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), 64, KAttachedDbName)); // invalid ROWID
       
   820 	TEST2(err, KSqlErrGeneral);
       
   821 	CleanupStack::PopAndDestroy(&rdStrm);
       
   822 	CleanupStack::PopAndDestroy(tooLongName);		
       
   823 	
       
   824 	// RSqlBlobReadStream::Source()::SeekL()
       
   825 	CleanupClosePushL(rdStrm);
       
   826 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   827 	TInt size = rdStrm.SizeL();
       
   828 	TEST(size > 0);
       
   829 	TStreamPos pos(-1);
       
   830 	TRAP(err, rdStrm.Source()->SeekL(MStreamBuf::ERead, pos));
       
   831 	TEST2(err, KErrEof);
       
   832 	TStreamPos pos2(size - 1);
       
   833 	TRAP(err, rdStrm.Source()->SeekL(MStreamBuf::ERead, pos2));
       
   834 	TEST2(err, KErrNone);
       
   835 	TStreamPos pos3(size + 1);
       
   836 	TRAP(err, rdStrm.Source()->SeekL(MStreamBuf::ERead, pos3));
       
   837 	TEST2(err, KErrEof);
       
   838 	CleanupStack::PopAndDestroy(&rdStrm);
       
   839 	
       
   840 	// RSqlBlobReadStream::ReadL()
       
   841 	CleanupClosePushL(rdStrm);
       
   842 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   843 	size = rdStrm.SizeL();
       
   844 	TEST2(size, 20);
       
   845 	TBuf8<20> dataBuf;
       
   846 	TBuf8<50> tooBigDataBuf;	
       
   847 	TRAP(err, rdStrm.ReadL(tooBigDataBuf));
       
   848 	TEST2(err, KErrEof);
       
   849 	rdStrm.Close();
       
   850 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   851 	TRAP(err, rdStrm.ReadL(tooBigDataBuf, size + 1));
       
   852 	TEST2(err, KErrEof);
       
   853 	rdStrm.Close();
       
   854 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   855 	TRAP(err, rdStrm.ReadL(tooBigDataBuf, TChar('J'))); // doesn't find 'J' so tries to fill the buffer to its max size
       
   856 	TEST2(err, KErrEof);
       
   857 	CleanupStack::PopAndDestroy(&rdStrm);
       
   858 	}
       
   859 	
       
   860 void BadParamWriteStreamL()
       
   861 	{
       
   862 	HBufC* tooLongName = HBufC::NewLC(KMaxFileName + 1);
       
   863 	TPtr tooLongNameDes = tooLongName->Des();
       
   864 	tooLongNameDes.Fill('A', KMaxFileName + 1);	
       
   865 	
       
   866 	// RSqlBlobWriteStream::OpenL()
       
   867 	RSqlBlobWriteStream wrStrm;
       
   868 	CleanupClosePushL(wrStrm);
       
   869 	TRAPD(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"))); // a successful open (on a BLOB column)
       
   870 	TEST2(err, KErrNone);
       
   871 	wrStrm.Close();
       
   872 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("T"))); // a successful open (on a TEXT column)
       
   873 	TEST2(err, KErrNone);
       
   874 	wrStrm.Close();
       
   875 	TRAP(err, wrStrm.OpenL(TheDb2, _L("table1"), _L("B"))); // wrong db connection
       
   876 	TEST2(err, KSqlErrGeneral);
       
   877 	TRAP(err, wrStrm.OpenL(TheDb1, _L(""), _L("B"))); // empty table name
       
   878 	TEST2(err, KErrBadName);
       
   879 	TRAP(err, wrStrm.OpenL(TheDb1, tooLongNameDes, _L("B"))); // too long table name
       
   880 	TEST2(err, KErrBadName);
       
   881 	TRAP(err, wrStrm.OpenL(TheDb1, _L("invalidTableName"), _L("B"))); // invalid table name
       
   882 	TEST2(err, KSqlErrGeneral);
       
   883 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L(""))); // empty column name
       
   884 	TEST2(err, KErrBadName);
       
   885 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), tooLongNameDes)); // too long column name
       
   886 	TEST2(err, KErrBadName);
       
   887 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("invalidColumnName"))); // invalid column name
       
   888 	TEST2(err, KSqlErrGeneral);
       
   889 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("I"))); // invalid column type
       
   890 	TEST2(err, KSqlErrGeneral);
       
   891 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"), 0)); // illegal ROWID
       
   892 	TEST2(err, KErrArgument);
       
   893 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"), 99)); // invalid ROWID
       
   894 	TEST2(err, KSqlErrGeneral);
       
   895 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"), KSqlLastInsertedRowId, _L("main"))); // a successful open (on a BLOB column)
       
   896 	TEST2(err, KErrNone);
       
   897 	wrStrm.Close();
       
   898 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"), KSqlLastInsertedRowId, _L(""))); // a successful open (on a BLOB column)
       
   899 	TEST2(err, KErrNone);
       
   900 	wrStrm.Close();
       
   901 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("T"), KSqlLastInsertedRowId, _L("main"))); // a successful open (on a TEXT column)
       
   902 	TEST2(err, KErrNone);
       
   903 	wrStrm.Close();
       
   904 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("T"), KSqlLastInsertedRowId, _L(""))); // a successful open (on a TEXT column)
       
   905 	TEST2(err, KErrNone);
       
   906 	wrStrm.Close();
       
   907 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on a BLOB column)
       
   908 	TEST2(err, KErrNone);
       
   909 	wrStrm.Close();
       
   910 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on a TEXT column)
       
   911 	TEST2(err, KErrNone);
       
   912 	wrStrm.Close();
       
   913 	TRAP(err, wrStrm.OpenL(TheDb2, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // wrong db connection
       
   914 	TEST2(err, KSqlErrGeneral);
       
   915 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), tooLongNameDes)); // too long attached db name
       
   916 	TEST2(err, KErrBadName);
       
   917 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), _L("invalidAttachedDbName"))); // invalid attached db name
       
   918 	TEST2(err, KSqlErrGeneral);
       
   919 	TRAP(err, wrStrm.OpenL(TheDb1, _L("invalidTableName"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid table name
       
   920 	TEST2(err, KSqlErrGeneral);
       
   921 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("invalidColumnName"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column name
       
   922 	TEST2(err, KSqlErrGeneral);
       
   923 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("int"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column type
       
   924 	TEST2(err, KSqlErrGeneral);
       
   925 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), 64, KAttachedDbName)); // invalid ROWID
       
   926 	TEST2(err, KSqlErrGeneral);
       
   927 	CleanupStack::PopAndDestroy(&wrStrm);
       
   928 	CleanupStack::PopAndDestroy(tooLongName);
       
   929 
       
   930 	// RSqlBlobWriteStream::Sink()::SeekL()
       
   931 	CleanupClosePushL(wrStrm);
       
   932 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   933 	TInt size = wrStrm.SizeL();
       
   934 	TEST(size > 0);
       
   935 	TStreamPos pos(-1);
       
   936 	TRAP(err, wrStrm.Sink()->SeekL(MStreamBuf::ERead, pos));
       
   937 	TEST2(err, KErrEof);
       
   938 	TStreamPos pos2(size - 1);
       
   939 	TRAP(err, wrStrm.Sink()->SeekL(MStreamBuf::ERead, pos2));
       
   940 	TEST2(err, KErrNone);
       
   941 	TStreamPos pos3(size + 1);
       
   942 	TRAP(err, wrStrm.Sink()->SeekL(MStreamBuf::ERead, pos3));
       
   943 	TEST2(err, KErrEof);
       
   944 	CleanupStack::PopAndDestroy(&wrStrm);
       
   945 	
       
   946 	// RSqlBlobWriteStream::WriteL()
       
   947 	CleanupClosePushL(wrStrm);
       
   948 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   949 	size = wrStrm.SizeL();
       
   950 	TEST2(size, 20);
       
   951 	TBuf8<50> tooBigDataBuf;
       
   952 	tooBigDataBuf.Fill('B', 50);	
       
   953 	TRAP(err, wrStrm.WriteL(tooBigDataBuf));
       
   954 #ifdef _DEBUG
       
   955 	TEST2(err, KErrEof);
       
   956 #else
       
   957 	TEST2(err, KErrNone);
       
   958 	TRAP(err, wrStrm.CommitL());
       
   959 	TEST2(err, KErrEof);
       
   960 #endif
       
   961 	wrStrm.Close();
       
   962 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
   963 	TRAP(err, wrStrm.WriteL(tooBigDataBuf, size + 1));
       
   964 #ifdef _DEBUG
       
   965 	TEST2(err, KErrEof);
       
   966 #else
       
   967 	TEST2(err, KErrNone);
       
   968 	TRAP(err, wrStrm.CommitL());
       
   969 	TEST2(err, KErrEof);
       
   970 #endif
       
   971 	CleanupStack::PopAndDestroy(&wrStrm);
       
   972 	}
       
   973 	
       
   974 void BadParamGetL()
       
   975 	{
       
   976 	HBufC* tooLongName = HBufC::NewLC(KMaxFileName + 1);
       
   977 	TPtr tooLongNameDes = tooLongName->Des();
       
   978 	tooLongNameDes.Fill('A', KMaxFileName + 1);	
       
   979 
       
   980 	// TSqlBlob::GetLC()	
       
   981 	HBufC8* wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B")); // a successful get (on a BLOB column)
       
   982 	TInt blobLength = wholeBuf->Length();
       
   983 	TEST(blobLength > 0);
       
   984 	CleanupStack::PopAndDestroy(wholeBuf); 
       
   985 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("T")); // a successful get (on a TEXT column)
       
   986 	blobLength = wholeBuf->Length();
       
   987 	TEST(blobLength > 0);
       
   988 	CleanupStack::PopAndDestroy(wholeBuf); 
       
   989 	TRAPD(err, wholeBuf = TSqlBlob::GetLC(TheDb2, _L("table1"), _L("B"))); // wrong db connection
       
   990 	TEST2(err, KSqlErrGeneral); 
       
   991 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L(""), _L("B"))); // empty table name
       
   992 	TEST2(err, KErrBadName); 
       
   993 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, tooLongNameDes, _L("B"))); // too long table name
       
   994 	TEST2(err, KErrBadName); 
       
   995 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("invalidTableName"), _L("B"))); // invalid table name
       
   996 	TEST2(err, KSqlErrGeneral); 
       
   997 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L(""))); // empty column name
       
   998 	TEST2(err, KErrBadName); 
       
   999 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), tooLongNameDes)); // too long column name
       
  1000 	TEST2(err, KErrBadName); 
       
  1001 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("invalidColumnName"))); // invalid column name
       
  1002 	TEST2(err, KSqlErrGeneral); 
       
  1003 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("I"))); // invalid column type
       
  1004 	TEST2(err, KSqlErrGeneral); 
       
  1005 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"), -2)); // illegal ROWID
       
  1006 	TEST2(err, KErrArgument); 
       
  1007 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"), 3731)); // invalid ROWID
       
  1008 	TEST2(err, KSqlErrGeneral); 
       
  1009 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId(), _L("main")); // a successful get (on a BLOB column)
       
  1010 	blobLength = wholeBuf->Length();
       
  1011 	TEST(blobLength > 0);
       
  1012 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1013 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId(), _L("")); // a successful get (on a BLOB column)
       
  1014 	blobLength = wholeBuf->Length();
       
  1015 	TEST(blobLength > 0);
       
  1016 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1017 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("T"), TheDb1.LastInsertedRowId(), _L("main")); // a successful get (on a TEXT column)
       
  1018 	blobLength = wholeBuf->Length();
       
  1019 	TEST(blobLength > 0);
       
  1020 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1021 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("T"), TheDb1.LastInsertedRowId(), _L("")); // a successful get (on a TEXT column)
       
  1022 	blobLength = wholeBuf->Length();
       
  1023 	TEST(blobLength > 0);
       
  1024 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1025 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on a BLOB column)
       
  1026 	blobLength = wholeBuf->Length();
       
  1027 	TEST(blobLength > 0);
       
  1028 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1029 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on a TEXT column)
       
  1030 	blobLength = wholeBuf->Length();
       
  1031 	TEST(blobLength > 0);
       
  1032 	CleanupStack::PopAndDestroy(wholeBuf);
       
  1033 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb2, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // wrong db connection
       
  1034 	TEST2(err, KSqlErrGeneral); 
       
  1035 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("invalidTableName"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid table name
       
  1036 	TEST2(err, KSqlErrGeneral); 
       
  1037 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("invalidColumnName"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column name
       
  1038 	TEST2(err, KSqlErrGeneral); 
       
  1039 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("int"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column type
       
  1040 	TEST2(err, KSqlErrGeneral); 
       
  1041 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), 345, KAttachedDbName)); // invalid ROWID
       
  1042 	TEST2(err, KSqlErrGeneral); 
       
  1043 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), _L("invalidAttachedDbName"))); // invalid attached db name
       
  1044 	TEST2(err, KSqlErrGeneral); 
       
  1045 	TRAP(err, wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), tooLongNameDes)); // too long attached db name
       
  1046 	TEST2(err, KErrBadName); 
       
  1047 
       
  1048 	// TSqlBlob::Get()
       
  1049 	HBufC8* buf = HBufC8::NewLC(50);
       
  1050 	TPtr8 bufPtr(buf->Des());	  	
       
  1051 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr); // a successful get (on a BLOB column)
       
  1052 	TEST2(err, KErrNone);
       
  1053 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("T"), bufPtr); // a successful get (on a TEXT column)
       
  1054 	TEST2(err, KErrNone); 
       
  1055 	err = TSqlBlob::Get(TheDb2, _L("table1"), _L("B"), bufPtr); // wrong db connection
       
  1056 	TEST2(err, KSqlErrGeneral); 
       
  1057 	err = TSqlBlob::Get(TheDb1, _L(""), _L("B"), bufPtr); // empty table name
       
  1058 	TEST2(err, KErrBadName); 
       
  1059 	err = TSqlBlob::Get(TheDb1, tooLongNameDes, _L("B"), bufPtr); // too long table name
       
  1060 	TEST2(err, KErrBadName);
       
  1061 	err = TSqlBlob::Get(TheDb1, _L("invalidTableName"), _L("B"), bufPtr); // invalid table name
       
  1062 	TEST2(err, KSqlErrGeneral); 
       
  1063 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L(""), bufPtr); // empty column name
       
  1064 	TEST2(err, KErrBadName); 
       
  1065 	err = TSqlBlob::Get(TheDb1, _L("table1"), tooLongNameDes, bufPtr); // too long column name
       
  1066 	TEST2(err, KErrBadName); 
       
  1067 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("invalidColumnName"), bufPtr); // invalid column name
       
  1068 	TEST2(err, KSqlErrGeneral); 
       
  1069 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("I"), bufPtr); // invalid column type
       
  1070 	TEST2(err, KSqlErrGeneral); 
       
  1071 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr, 0); // illegal ROWID
       
  1072 	TEST2(err, KErrArgument); 
       
  1073 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr, 3731); // invalid ROWID
       
  1074 	TEST2(err, KSqlErrGeneral); 
       
  1075 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr, TheDb1.LastInsertedRowId(), _L("main")); // a successful get (on a BLOB column)
       
  1076 	TEST2(err, KErrNone); 
       
  1077 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), bufPtr, TheDb1.LastInsertedRowId(), _L("")); // a successful get (on a BLOB column)
       
  1078 	TEST2(err, KErrNone); 
       
  1079 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("T"), bufPtr, TheDb1.LastInsertedRowId(), _L("main")); // a successful get (on a TEXT column)
       
  1080 	TEST2(err, KErrNone); 
       
  1081 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("T"), bufPtr, TheDb1.LastInsertedRowId(), _L("")); // a successful get (on a TEXT column)
       
  1082 	TEST2(err, KErrNone); 
       
  1083 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on a BLOB column)
       
  1084 	TEST2(err, KErrNone); 
       
  1085 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("text"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on a TEXT column)
       
  1086 	TEST2(err, KErrNone); 
       
  1087 	err = TSqlBlob::Get(TheDb2, _L("table2"), _L("blob"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // wrong db connection
       
  1088 	TEST2(err, KSqlErrGeneral); 
       
  1089 	err = TSqlBlob::Get(TheDb1, _L("invalidTableName"), _L("blob"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // invalid table name
       
  1090 	TEST2(err, KSqlErrGeneral); 
       
  1091 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("invalidColumnName"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // invalid column name
       
  1092 	TEST2(err, KSqlErrGeneral); 
       
  1093 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("int"), bufPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // invalid column type
       
  1094 	TEST2(err, KSqlErrGeneral); 
       
  1095 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), bufPtr, 345, KAttachedDbName); // invalid ROWID
       
  1096 	TEST2(err, KSqlErrGeneral); 
       
  1097 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), bufPtr, TheDb2.LastInsertedRowId(), _L("invalidAttachedDbName")); // invalid attached db name
       
  1098 	TEST2(err, KSqlErrGeneral); 
       
  1099 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), bufPtr, TheDb2.LastInsertedRowId(), tooLongNameDes); // too long attached db name
       
  1100 	TEST2(err, KErrBadName);
       
  1101 	CleanupStack::PopAndDestroy(buf);	
       
  1102 	
       
  1103 	CleanupStack::PopAndDestroy(tooLongName);
       
  1104 	}
       
  1105 
       
  1106 void BadParamSetL()
       
  1107 	{
       
  1108 	HBufC* tooLongName = HBufC::NewLC(KMaxFileName + 1);
       
  1109 	TPtr tooLongNameDes = tooLongName->Des();
       
  1110 	tooLongNameDes.Fill('A', KMaxFileName + 1);	
       
  1111 	
       
  1112 	// TSqlBlob::SetL()
       
  1113 	TRAPD(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("twenty characters !!"))); // a successful set (on a BLOB column)
       
  1114 	TEST2(err, KErrNone); 
       
  1115 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("T"), _L8("twenty characters !!"))); // a successful set (on a TEXT column)
       
  1116 	TEST2(err, KErrNone); 
       
  1117 	TRAP(err, TSqlBlob::SetL(TheDb2, _L("table1"), _L("B"), _L8("twenty characters..."))); // wrong db connection
       
  1118 	TEST2(err, KSqlErrGeneral);
       
  1119 	TRAP(err, TSqlBlob::SetL(TheDb1, _L(""), _L("B"), _L8("twenty characters..."))); // empty table name
       
  1120 	TEST2(err, KErrBadName); 
       
  1121 	TRAP(err, TSqlBlob::SetL(TheDb1, tooLongNameDes, _L("B"), _L8("twenty characters..."))); // too long table name
       
  1122 	TEST2(err, KErrBadName);   
       
  1123 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("invalidTableName"), _L("B"), _L8("twenty characters..."))); // invalid table name
       
  1124 	TEST2(err, KSqlErrGeneral); 
       
  1125 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L(""), _L8("twenty characters..."))); // empty column name
       
  1126 	TEST2(err, KErrBadName); 
       
  1127 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), tooLongNameDes, _L8("twenty characters..."))); // too long column name
       
  1128 	TEST2(err, KErrBadName); 
       
  1129 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("invalidColumnName"), _L8("twenty characters..."))); // invalid column name
       
  1130 	TEST2(err, KSqlErrGeneral); 
       
  1131 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("I"), _L8("twenty characters..."))); // invalid column type
       
  1132 	TEST2(err, KSqlErrGeneral);
       
  1133 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("twenty characters..."), -3));  // illegal ROWID
       
  1134 	TEST2(err, KErrArgument);
       
  1135 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("twenty characters..."), 1113));  // invalid ROWID
       
  1136 	TEST2(err, KSqlErrGeneral); 
       
  1137 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("!!!twenty characters"), TheDb1.LastInsertedRowId(), _L("main"))); // a successful set (on a BLOB column)
       
  1138 	TEST2(err, KErrNone); 
       
  1139 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("!!!twenty characters"), TheDb1.LastInsertedRowId(), _L(""))); // a successful set (on a BLOB column)
       
  1140 	TEST2(err, KErrNone); 
       
  1141 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("T"), _L8("!!!twenty characters"), TheDb1.LastInsertedRowId(), _L("main"))); // a successful set (on a TEXT column)
       
  1142 	TEST2(err, KErrNone); 
       
  1143 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("T"), _L8("!!!twenty characters"), TheDb1.LastInsertedRowId(), _L(""))); // a successful set (on a TEXT column)
       
  1144 	TEST2(err, KErrNone); 
       
  1145 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), _L8("10 chars!!"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful set (on a BLOB column)
       
  1146 	TEST2(err, KErrNone); 
       
  1147 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("text"), _L8("10 chars!!"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful set (on a TEXT column)
       
  1148 	TEST2(err, KErrNone); 
       
  1149 	TRAP(err, TSqlBlob::SetL(TheDb2, _L("table2"), _L("blob"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), KAttachedDbName)); // wrong db connection
       
  1150 	TEST2(err, KSqlErrGeneral); 
       
  1151 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("invalidTableName"), _L("blob"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid table name
       
  1152 	TEST2(err, KSqlErrGeneral); 
       
  1153 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("invalidColumnName"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column name
       
  1154 	TEST2(err, KSqlErrGeneral); 
       
  1155 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("int"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), KAttachedDbName)); // invalid column type
       
  1156 	TEST2(err, KSqlErrGeneral); 
       
  1157 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), _L8("10 chars.."), 13, KAttachedDbName)); // invalid ROWID
       
  1158 	TEST2(err, KSqlErrGeneral); 
       
  1159 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), _L("invalidAttachedDbName"))); // invalid attached db name
       
  1160 	TEST2(err, KSqlErrGeneral); 	
       
  1161 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), _L8("10 chars.."), TheDb2.LastInsertedRowId(), tooLongNameDes)); // too long attached db name
       
  1162 	TEST2(err, KErrBadName); 
       
  1163 	
       
  1164 	CleanupStack::PopAndDestroy(tooLongName);
       
  1165 	}
       
  1166 	
       
  1167 void BadParamBindZeroBlobL()
       
  1168 	{
       
  1169 	// RSqlStatement::BindZeroBlob()
       
  1170 	RSqlBlobReadStream rdStrm;
       
  1171 	CleanupClosePushL(rdStrm);
       
  1172 	RSqlStatement stmt;
       
  1173 	CleanupClosePushL(stmt);
       
  1174 	TInt err = stmt.Prepare(TheDb2, _L("INSERT INTO table2 values(1, 'dummy text', :Val)"));
       
  1175 	TEST2(err, KErrNone);
       
  1176 	TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
       
  1177 	TEST(paramIndex >= 0);	
       
  1178 	err = stmt.BindZeroBlob(paramIndex, -1); // a negative blob size
       
  1179 	TEST2(err, KErrNone);
       
  1180 	err = stmt.Exec();
       
  1181 	TEST2(err, 1);
       
  1182 	stmt.Reset();
       
  1183 	rdStrm.OpenL(TheDb2, _L("table2"), _L("blob"));
       
  1184 	TInt size = rdStrm.SizeL(); // check the blob's size is 0 (0 is used if a negative number was specified)
       
  1185 	TEST2(size, 0);
       
  1186 	rdStrm.Close();
       
  1187 	err = stmt.BindZeroBlob(paramIndex, 0); // a blob size of zero
       
  1188 	TEST2(err, KErrNone);
       
  1189 	err = stmt.Exec();
       
  1190 	TEST2(err, 1);
       
  1191 	stmt.Reset();
       
  1192 	rdStrm.OpenL(TheDb2, _L("table2"), _L("blob"));
       
  1193 	size = rdStrm.SizeL(); // check the blob's size is 0
       
  1194 	TEST2(size, 0);
       
  1195 	// For subsequent test purposes make the last inserted record have a zeroblob > 0 size
       
  1196 	err = stmt.BindZeroBlob(paramIndex, 1);
       
  1197 	TEST2(err, KErrNone);
       
  1198 	err = stmt.Exec();
       
  1199 	TEST2(err, 1);
       
  1200 	CleanupStack::PopAndDestroy(&stmt);		
       
  1201 	CleanupStack::PopAndDestroy(&rdStrm);	
       
  1202 	}
       
  1203 	
       
  1204 /**
       
  1205 @SYMTestCaseID			SYSLIB-SQL-UT-4107
       
  1206 @SYMTestCaseDesc		Bad parameter tests for the methods of RSqlBlobReadStream, 
       
  1207 						RSqlBlobWriteStream, TSqlBlob and RSqlStatement::BindZeroBlob().
       
  1208 						Tests that the correct error code is returned when a bad parameter
       
  1209 						is used in a call to one of the methods.
       
  1210 						Tests the RSqlBlobReadStream, RSqlBlobWriteStream and TSqlBlob methods
       
  1211 						and RSqlStatement::BindZeroBlob().
       
  1212 @SYMTestPriority		High
       
  1213 @SYMTestActions			Execution of bad parameter tests.
       
  1214 @SYMTestExpectedResults Test must not fail
       
  1215 @SYMREQ					REQ10411
       
  1216                         REQ10418
       
  1217 */
       
  1218 void BadParamTestL()
       
  1219 	{
       
  1220 	BadParamReadStreamL();	
       
  1221 	BadParamWriteStreamL();	
       
  1222 	BadParamGetL();
       
  1223 	BadParamSetL();	
       
  1224 	BadParamBindZeroBlobL();
       
  1225 	}
       
  1226 
       
  1227 /**
       
  1228 @SYMTestCaseID			SYSLIB-SQL-UT-4108
       
  1229 @SYMTestCaseDesc		Indexed column tests for the methods of RSqlBlobReadStream
       
  1230 						and RSqlBlobWriteStream, to ensure that a blob or text column
       
  1231 						that is indexed cannot be written to but can be read from 
       
  1232 						(an SQLite restriction).
       
  1233 @SYMTestPriority		Medium
       
  1234 @SYMTestActions			Execution of read and write operations on an indexed column in a database.
       
  1235 @SYMTestExpectedResults Test must not fail
       
  1236 @SYMREQ					REQ10411
       
  1237                         REQ10418
       
  1238 */	
       
  1239 void IndexedColumnTestL()
       
  1240 	{
       
  1241 	// Create an index on the BLOB column and on the TEXT column in the main and attached databases
       
  1242 	CreateIndices();
       
  1243 
       
  1244 	// Attempt to open a write stream on an indexed BLOB and an indexed TEXT column - this should not be permitted.
       
  1245 	// (This is an SQLite restriction, but having an index on a large BLOB or a TEXT column is highly unlikely!)
       
  1246 	RSqlBlobWriteStream wrStrm;
       
  1247 	CleanupClosePushL(wrStrm);
       
  1248 	TRAPD(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("B"))); // indexed BLOB column
       
  1249 	TEST2(err, KSqlErrGeneral);
       
  1250 	wrStrm.Close();
       
  1251 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table1"), _L("T"))); // indexed TEXT column
       
  1252 	TEST2(err, KSqlErrGeneral);
       
  1253 	wrStrm.Close();
       
  1254 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // indexed BLOB column
       
  1255 	TEST2(err, KSqlErrGeneral);
       
  1256 	wrStrm.Close();
       
  1257 	TRAP(err, wrStrm.OpenL(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // indexed TEXT column
       
  1258 	TEST2(err, KSqlErrGeneral);
       
  1259 	CleanupStack::PopAndDestroy(&wrStrm);
       
  1260 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("twenty characters !!"))); // indexed BLOB column
       
  1261 	TEST2(err, KSqlErrGeneral); 
       
  1262 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("T"), _L8("twenty characters !!"))); // indexed TEXT column
       
  1263 	TEST2(err, KSqlErrGeneral); 
       
  1264 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("blob"), _L8("10 chars!!"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // indexed BLOB column
       
  1265 	TEST2(err, KSqlErrGeneral); 
       
  1266 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table2"), _L("text"), _L8("10 chars!!"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // indexed TEXT column
       
  1267 	TEST2(err, KSqlErrGeneral);
       
  1268 	
       
  1269 	// Attempt to open a read stream on an indexed BLOB and an indexed text COLUMN - this should be permitted
       
  1270 	RSqlBlobReadStream rdStrm;
       
  1271 	CleanupClosePushL(rdStrm);
       
  1272 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("B"))); // a successful open (on an indexed BLOB column)
       
  1273 	TEST2(err, KErrNone);
       
  1274 	rdStrm.Close();
       
  1275 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table1"), _L("T"))); // a successful open (on an indexed TEXT column)
       
  1276 	TEST2(err, KErrNone);
       
  1277 	rdStrm.Close();
       
  1278 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on an indexed BLOB column)
       
  1279 	TEST2(err, KErrNone);
       
  1280 	rdStrm.Close();
       
  1281 	TRAP(err, rdStrm.OpenL(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName)); // a successful open (on an indexed TEXT column)
       
  1282 	TEST2(err, KErrNone);
       
  1283 	CleanupStack::PopAndDestroy(&rdStrm);
       
  1284 	HBufC8* wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("B")); // a successful get (on an indexed BLOB column)
       
  1285 	TInt blobLength = wholeBuf->Length();
       
  1286 	TEST(blobLength > 0);
       
  1287 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1288 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("T")); // a successful get (on an indexed TEXT column)
       
  1289 	blobLength = wholeBuf->Length();
       
  1290 	TEST(blobLength > 0);
       
  1291 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1292 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("blob"), TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on an indexed BLOB column)
       
  1293 	blobLength = wholeBuf->Length();
       
  1294 	TEST(blobLength > 0);
       
  1295 	CleanupStack::PopAndDestroy(wholeBuf); 	
       
  1296 	wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table2"), _L("text"), TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on an indexed TEXT column)
       
  1297 	blobLength = wholeBuf->Length();
       
  1298 	TEST(blobLength > 0);
       
  1299 	CleanupStack::PopAndDestroy(wholeBuf);
       
  1300 	HBufC8* buf = HBufC8::NewLC(50);
       
  1301 	TPtr8 buffPtr(buf->Des());	  	
       
  1302 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), buffPtr); // a successful get (on an indexed BLOB column)
       
  1303 	TEST2(err, KErrNone); 
       
  1304 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("T"), buffPtr); // a successful get (on an indexed TEXT column)
       
  1305 	TEST2(err, KErrNone); 
       
  1306 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("blob"), buffPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on an indexed BLOB column)
       
  1307 	TEST2(err, KErrNone); 
       
  1308 	err = TSqlBlob::Get(TheDb1, _L("table2"), _L("text"), buffPtr, TheDb2.LastInsertedRowId(), KAttachedDbName); // a successful get (on an indexed TEXT column)
       
  1309 	TEST2(err, KErrNone);
       
  1310 	CleanupStack::PopAndDestroy(buf);
       
  1311 	
       
  1312 	RemoveIndices();
       
  1313 	}
       
  1314 	
       
  1315 /**
       
  1316 @SYMTestCaseID			SYSLIB-SQL-UT-4109
       
  1317 @SYMTestCaseDesc		'End of file' tests for the methods of RSqlBlobReadStream
       
  1318 						RSqlBlobWriteStream and TSqlBlob, to ensure that a client cannot
       
  1319 						read beyond the end of a blob object or write beyond the end of a 
       
  1320 						blob object and that an appropriate error code is returned.
       
  1321 @SYMTestPriority		High
       
  1322 @SYMTestActions			Execution of read and write operations beyond the end of a blob object.
       
  1323 @SYMTestExpectedResults Test must not fail
       
  1324 @SYMREQ					REQ10411
       
  1325                         REQ10418
       
  1326 */	
       
  1327 void EofTestL()
       
  1328 	{
       
  1329 	// Use Blob 3 in table1, whose value is "!!!twenty characters"
       
  1330 	
       
  1331 	// Read Eof tests
       
  1332 
       
  1333 	const TInt KBlobSize = 20;	
       
  1334 	RSqlBlobReadStream rdStrm;
       
  1335 	CleanupClosePushL(rdStrm);
       
  1336 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1337 	TInt size = rdStrm.SizeL(); 
       
  1338 	TEST2(size, KBlobSize);
       
  1339 	TBuf8<50> data;
       
  1340 	TRAPD(err, rdStrm.ReadL(data, KBlobSize));
       
  1341 	TEST2(err, KErrNone); 
       
  1342 	TEST(data.Compare(_L8("!!!twenty characters")) == 0);
       
  1343 	TRAP(err, rdStrm.ReadL(data, 1));
       
  1344 	TEST2(err, KErrEof);
       
  1345 	rdStrm.Close();
       
  1346 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1347 	TRAP(err, rdStrm.ReadL(data, 21));
       
  1348 	TEST2(err, KErrEof); 
       
  1349 	rdStrm.Close();
       
  1350 	
       
  1351 	HBufC8* exactSizeBuf = HBufC8::NewLC(KBlobSize);	
       
  1352 	TPtr8 exactSizeBufPtr(exactSizeBuf->Des());	  	  
       
  1353 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), exactSizeBufPtr);
       
  1354 	TEST2(err, KErrNone); 
       
  1355 	TEST(exactSizeBufPtr.Compare(_L8("!!!twenty characters")) == 0);
       
  1356 	CleanupStack::PopAndDestroy(exactSizeBuf);	
       
  1357 	
       
  1358 	HBufC8* tooSmallBuf = HBufC8::NewLC(KBlobSize/2);	
       
  1359 	TPtr8 tooSmallBufPtr(tooSmallBuf->Des());	  	  			  		  	  
       
  1360 	err = TSqlBlob::Get(TheDb1, _L("table1"), _L("B"), tooSmallBufPtr);
       
  1361 	TEST2(err, KErrOverflow); 	
       
  1362 	CleanupStack::PopAndDestroy(tooSmallBuf);	
       
  1363 	
       
  1364 	// Write Eof tests
       
  1365 	
       
  1366 	RSqlBlobWriteStream wrStrm;
       
  1367 	CleanupClosePushL(wrStrm);
       
  1368 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1369 	size = wrStrm.SizeL();
       
  1370 	TEST2(size, KBlobSize);
       
  1371 	// For debug builds: This 20 bytes will be written to the blob straight away
       
  1372 	// because 20 bytes is more than the 8 byte buffer
       
  1373 	// For release builds: This 20 bytes will NOT be written to the blob straight away
       
  1374 	// because there is room for it to be stored in the 1.5K byte buffer
       
  1375 	TRAP(err, wrStrm.WriteL(_L8("a twenty char string"))); 
       
  1376 	TEST2(err, KErrNone);
       
  1377 	// For debug/release builds: This 1 byte will NOT be written to the blob straight away
       
  1378 	// because there is room for it to be stored in the 8 byte/1.5K buffer
       
  1379 	TRAP(err, wrStrm.WriteL(_L8("a")));
       
  1380 	TEST2(err, KErrNone);
       
  1381 	// For debug builds: The CommitL() call will cause an attempt to write the 1 byte 
       
  1382 	// in the buffer to the blob - however, the stream's write position indicates 
       
  1383 	// that the write would be beyond the end of the blob and so an error occurs
       
  1384 	// For release builds: The CommitL() call will cause an attempt to write the 21 bytes 
       
  1385 	// in the buffer to the blob - however, 21 bytes is larger than the size of the blob
       
  1386 	// and so an error occurs
       
  1387 	TRAP(err, wrStrm.CommitL());
       
  1388 	TEST2(err, KErrEof);	
       
  1389 	wrStrm.Close();
       
  1390 	// For debug builds: Check that the blob value is now "a twenty char string"
       
  1391 	// For release builds: Check that the blob value is still "!!!twenty characters"
       
  1392 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1393 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1394 	TEST2(err, KErrNone); 
       
  1395 #ifdef _DEBUG	
       
  1396 	TEST(data.Compare(_L8("a twenty char string")) == 0);
       
  1397 #else	
       
  1398 	TEST(data.Compare(_L8("!!!twenty characters")) == 0);
       
  1399 #endif
       
  1400 	rdStrm.Close();
       
  1401 	
       
  1402 	TheDb1.Exec(_L("BEGIN"));
       
  1403 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1404 	// For debug/release builds: These 3 bytes will be stored in the 8 byte/1.5K buffer
       
  1405 	TRAP(err, wrStrm.WriteL(_L8("eee"))); 
       
  1406 	TEST2(err, KErrNone);
       
  1407 	// For debug builds: These 25 bytes will not fit in the 8 byte buffer and so an attempt 
       
  1408 	// will be made to write these 25 bytes and the 3 buffered bytes to the blob - 
       
  1409 	// however, the size of the blob is only 20 and so an error occurs
       
  1410 	// For release builds: These 25 bytes will be stored in the 1.5K buffer
       
  1411 	TRAP(err, wrStrm.WriteL(_L8("fffffffffffffffffffffffff"))); 
       
  1412 #ifdef _DEBUG
       
  1413 	TEST2(err, KErrEof);
       
  1414 	wrStrm.Close();
       
  1415 	TheDb1.Exec(_L("ROLLBACK"));
       
  1416 
       
  1417 	// Check that the blob value is still "a twenty char string"
       
  1418 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1419 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1420 	TEST2(err, KErrNone); 
       
  1421 	TEST(data.Compare(_L8("a twenty char string")) == 0);
       
  1422 	rdStrm.Close();
       
  1423 #else
       
  1424 	TEST2(err, KErrNone);
       
  1425 	// For release builds: The CommitL() call will cause an attempt to write the 28 bytes 
       
  1426 	// in the buffer to the blob - however, 28 bytes is larger than the size of the blob
       
  1427 	// and so an error occurs
       
  1428 	TRAP(err, wrStrm.CommitL());
       
  1429 	TEST2(err, KErrEof);
       
  1430 	wrStrm.Close();
       
  1431 	TheDb1.Exec(_L("ROLLBACK"));
       
  1432 	
       
  1433 	// Check that the blob value is still "!!!twenty characters"
       
  1434 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1435 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1436 	TEST2(err, KErrNone); 
       
  1437 	TEST(data.Compare(_L8("!!!twenty characters")) == 0);
       
  1438 	rdStrm.Close();
       
  1439 #endif
       
  1440 
       
  1441 	TheDb1.Exec(_L("BEGIN"));
       
  1442 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1443 	TRAP(err, wrStrm.WriteL(_L8("a string that is longer than 20 characters"))); 	
       
  1444 #ifdef _DEBUG	
       
  1445 	TEST2(err, KErrEof);
       
  1446 	wrStrm.Close();
       
  1447 	TheDb1.Exec(_L("ROLLBACK"));
       
  1448 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1449 	TRAP(err, wrStrm.WriteL(_L8("ggg"))); 
       
  1450 	TEST2(err, KErrNone);
       
  1451 	TRAP(err, wrStrm.CommitL());
       
  1452 	TEST2(err, KErrNone);
       
  1453 	CleanupStack::PopAndDestroy(&wrStrm);	
       
  1454 	// Check that the blob value is now "gggwenty char string"
       
  1455 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1456 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1457 	TEST2(err, KErrNone); 
       
  1458 	TEST(data.Compare(_L8("gggwenty char string")) == 0);
       
  1459 	rdStrm.Close();
       
  1460 #else
       
  1461 	TEST2(err, KErrNone);
       
  1462 	TRAP(err, wrStrm.CommitL());
       
  1463 	TEST2(err, KErrEof);
       
  1464 	wrStrm.Close();
       
  1465 	TheDb1.Exec(_L("ROLLBACK"));
       
  1466 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1467 	TRAP(err, wrStrm.WriteL(_L8("hhh"))); 
       
  1468 	TEST2(err, KErrNone);
       
  1469 	TRAP(err, wrStrm.CommitL());
       
  1470 	TEST2(err, KErrNone);
       
  1471 	CleanupStack::PopAndDestroy(&wrStrm);		
       
  1472 	// Check that the blob value is now "hhhtwenty characters"
       
  1473 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1474 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1475 	TEST2(err, KErrNone); 
       
  1476 	TEST(data.Compare(_L8("hhhtwenty characters")) == 0);
       
  1477 	rdStrm.Close();
       
  1478 #endif
       
  1479 
       
  1480 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("a twenty char string")));
       
  1481 	TEST2(err, KErrNone); 
       
  1482 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1483 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1484 	TEST2(err, KErrNone); 
       
  1485 	TEST(data.Compare(_L8("a twenty char string")) == 0);
       
  1486 	rdStrm.Close();
       
  1487 
       
  1488 	TheDb1.Exec(_L("BEGIN"));
       
  1489 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("a string that is longer than 20 characters")));
       
  1490 	TEST2(err, KErrEof);
       
  1491 	TheDb1.Exec(_L("ROLLBACK"));
       
  1492 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1493 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1494 	TEST2(err, KErrNone); 
       
  1495 	TEST(data.Compare(_L8("a twenty char string")) == 0);
       
  1496 	rdStrm.Close();
       
  1497 	
       
  1498 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("B"), _L8("less than 20")));
       
  1499 	TEST2(err, KErrNone); 
       
  1500 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1501 	TRAP(err, rdStrm.ReadL(data, KBlobSize));
       
  1502 	TEST2(err, KErrNone); // changing only part of the blob data is permitted
       
  1503 	TEST(data.Compare(_L8("less than 20r string")) == 0);
       
  1504 	rdStrm.Close();
       
  1505 
       
  1506 	CleanupStack::PopAndDestroy(&rdStrm);	
       
  1507 	}
       
  1508 	
       
  1509 /**
       
  1510 @SYMTestCaseID			SYSLIB-SQL-UT-4110
       
  1511 @SYMTestCaseDesc		General blob read and write tests on a private secure database,
       
  1512 						to ensure that there are no security issues with the methods of 
       
  1513 						RSqlBlobReadStream, RSqlBlobWriteStream and TSqlBlob.
       
  1514 @SYMTestPriority		High
       
  1515 @SYMTestActions			Execution of read and write operations on a private secure database.
       
  1516 @SYMTestExpectedResults Test must not fail
       
  1517 @SYMREQ					REQ10411
       
  1518                         REQ10418
       
  1519 						REQ5794
       
  1520 */	
       
  1521 void PrivateSecureDbTestL()
       
  1522 	{
       
  1523 	// The blob has the value 'ABABABABABABABA'
       
  1524 	
       
  1525 	// Read data from the blob
       
  1526 	const TInt KBlobSize = 15;
       
  1527 	RSqlBlobReadStream rdStrm;
       
  1528 	CleanupClosePushL(rdStrm);
       
  1529 	rdStrm.OpenL(ThePrivateDb, _L("table3"), _L("picture"));
       
  1530 	TInt size = rdStrm.SizeL(); // check the blob's size
       
  1531 	TEST2(size, KBlobSize); 
       
  1532 	TBuf8<50> data;
       
  1533 	rdStrm.ReadL(data, 5);
       
  1534 	TEST(data.Compare(_L8("ABABA")) == 0); // check 5 bytes have been read
       
  1535 	rdStrm.ReadL(data, 8);
       
  1536 	TEST(data.Compare(_L8("BABABABA")) == 0);	// check the next 8 bytes have been read
       
  1537 	rdStrm.SizeL(); // check the blob's size
       
  1538 	TEST2(size, KBlobSize); 
       
  1539 	CleanupStack::PopAndDestroy(&rdStrm);
       
  1540 
       
  1541 	HBufC8* wholeBuf = TSqlBlob::GetLC(ThePrivateDb, _L("table3"), _L("picture"));
       
  1542 	TInt blobLength = wholeBuf->Length();
       
  1543 	TEST2(blobLength, KBlobSize);
       
  1544 	TEST(wholeBuf->Des().Compare(_L8("ABABABABABABABA")) == 0);	
       
  1545 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1546 	
       
  1547 	HBufC8* buf = HBufC8::NewLC(KBlobSize);	
       
  1548 	TPtr8 bufPtr(buf->Des());	  
       
  1549 	TInt err = TSqlBlob::Get(ThePrivateDb, _L("table3"), _L("picture"), bufPtr);
       
  1550 	TEST2(err, KErrNone); 
       
  1551 	TEST(bufPtr.Compare(_L8("ABABABABABABABA")) == 0);	
       
  1552 	CleanupStack::PopAndDestroy(buf); 
       
  1553 	
       
  1554 	// Write data to the blob 
       
  1555 	RSqlBlobWriteStream wrStrm;
       
  1556 	CleanupClosePushL(wrStrm);
       
  1557 	wrStrm.OpenL(ThePrivateDb, _L("table3"), _L("picture"));
       
  1558 	size = wrStrm.SizeL(); // check the blob's size
       
  1559 	TEST2(size, KBlobSize); 
       
  1560 	wrStrm.WriteL(_L8("AABBCC")); // write 6 bytes
       
  1561 	wrStrm.WriteL(_L8("DD")); // write another 2 bytes
       
  1562 	wrStrm.WriteL(_L8("EEFFG")); // write another 5 bytes
       
  1563 	size = wrStrm.SizeL(); // check the blob's size
       
  1564 	TEST2(size, KBlobSize); 
       
  1565 	wrStrm.CommitL();
       
  1566 	CleanupStack::PopAndDestroy(&wrStrm);
       
  1567 	
       
  1568 	// Check that the new blob data was written
       
  1569 	HBufC8* retrievedDataBuf = TSqlBlob::GetLC(ThePrivateDb, _L("table3"), _L("picture"));
       
  1570 	blobLength = retrievedDataBuf->Size();
       
  1571 	TEST2(blobLength, KBlobSize);
       
  1572 	TEST(retrievedDataBuf->Des().Compare(_L8("AABBCCDDEEFFGBA")) == 0);		
       
  1573 	CleanupStack::PopAndDestroy(retrievedDataBuf);
       
  1574 	
       
  1575 	HBufC8* dataBuf = HBufC8::NewLC(KBlobSize);
       
  1576 	TPtr8 dataPtr(dataBuf->Des());
       
  1577 	dataPtr.Append(_L8("CDCDCDCDCDCDCDC"));
       
  1578 	TSqlBlob::SetL(ThePrivateDb, _L("table3"), _L("picture"), dataPtr);
       
  1579 	CleanupStack::PopAndDestroy(dataBuf); 
       
  1580 	
       
  1581 	// Check that the new blob data was written
       
  1582 	retrievedDataBuf = TSqlBlob::GetLC(ThePrivateDb, _L("table3"), _L("picture"));
       
  1583 	blobLength = retrievedDataBuf->Size();
       
  1584 	TEST2(blobLength, KBlobSize);
       
  1585 	TEST(retrievedDataBuf->Des().Compare(_L8("CDCDCDCDCDCDCDC")) == 0);		
       
  1586 	CleanupStack::PopAndDestroy(retrievedDataBuf);
       
  1587 	}
       
  1588 	
       
  1589 /**
       
  1590 @SYMTestCaseID			SYSLIB-SQL-UT-4111
       
  1591 @SYMTestCaseDesc		Concurrent blob read and write tests using the 
       
  1592 						methods of RSqlBlobReadStream and RSqlBlobWriteStream.
       
  1593 						Tests that read and write operations on different blobs
       
  1594 						can happen concurrently and that read operations on the
       
  1595 						same blob from different streams can happen concurrently.
       
  1596 @SYMTestPriority		Medium
       
  1597 @SYMTestActions			Execution of concurrent blob read and write operations on a database.
       
  1598 @SYMTestExpectedResults Test must not fail
       
  1599 @SYMREQ					REQ10411
       
  1600                         REQ10418
       
  1601 */	
       
  1602 void ConcurrentReadAndWriteTestL()
       
  1603 	{	
       
  1604 	// Insert a zeroblob of size 2Kb
       
  1605 	InsertSQLiteZeroBlob(KLargeDataBufLen);
       
  1606 	// Insert a zeroblob of size 4Kb 
       
  1607 	InsertBindZeroBlob(4 * 1024);
       
  1608 	
       
  1609 	// Handles on different blobs
       
  1610 	
       
  1611 	// Write and read from different blobs
       
  1612 	RSqlBlobReadStream rdStrm;
       
  1613 	CleanupClosePushL(rdStrm);
       
  1614 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId() - 1);
       
  1615 
       
  1616 	RSqlBlobWriteStream wrStrm;
       
  1617 	CleanupClosePushL(wrStrm);
       
  1618 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1619 	
       
  1620 	wrStrm.WriteL(_L8("GHIJKL")); // blob2 is not updated in cache (as client buffer not full)
       
  1621 	TBuf8<100> data;
       
  1622 	rdStrm.ReadL(data, 6);
       
  1623 	_LIT8(KSixZeros, "\x0\x0\x0\x0\x0\x0");
       
  1624 	TEST(data.Compare(KSixZeros) == 0);		
       
  1625 	wrStrm.CommitL(); // blob2 update is not committed (as the rdStrm handle is open)
       
  1626 	wrStrm.Close();
       
  1627 	rdStrm.ReadL(data, 6);
       
  1628 	TEST(data.Compare(KSixZeros) == 0);	
       
  1629 	rdStrm.Close();	// the blob2 update is committed
       
  1630 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId() - 1);
       
  1631 	rdStrm.ReadL(data, 2); // read 2 bytes
       
  1632 	_LIT8(KTwoZeros, "\x0\x0");
       
  1633 	TEST(data.Compare(KTwoZeros) == 0);	
       
  1634 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1635 	wrStrm.WriteL(TheLargeData); // blob2 is updated in the cache	
       
  1636 	rdStrm.ReadL(data, 10); // read the next 10 bytes
       
  1637 	_LIT8(KTenZeros, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0");
       
  1638 	TEST(data.Compare(KTenZeros) == 0);	
       
  1639 	rdStrm.Close();
       
  1640 	wrStrm.CommitL(); // the blob2 update is committed
       
  1641 	CleanupStack::PopAndDestroy(2);
       
  1642 	
       
  1643 	// Write to different blobs via different streams
       
  1644 	CleanupClosePushL(wrStrm);
       
  1645 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId() - 1);
       
  1646 
       
  1647 	RSqlBlobWriteStream wrStrm2;
       
  1648 	CleanupClosePushL(wrStrm2);
       
  1649 	wrStrm2.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1650 	
       
  1651 	wrStrm.WriteL(_L8("ABABABABABABAB"));
       
  1652 	wrStrm2.WriteL(_L8("CDCDCD"));
       
  1653 	wrStrm.WriteL(_L8("EFEF"));
       
  1654 	wrStrm.Close();
       
  1655 	wrStrm2.Close(); // the blob1 update is committed and the blob2 update is committed 
       
  1656 	CleanupClosePushL(rdStrm);
       
  1657 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId() - 1);
       
  1658 	rdStrm.ReadL(data, 18);
       
  1659 	TEST(data.Compare(_L8("ABABABABABABABEFEF")) == 0);	
       
  1660 	rdStrm.Close();
       
  1661 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1662 	rdStrm.ReadL(data, 6);
       
  1663 	TEST(data.Compare(_L8("CDCDCD")) == 0);	
       
  1664 	rdStrm.Close();
       
  1665 	CleanupStack::PopAndDestroy(3); 
       
  1666 	
       
  1667 	// Read from different blobs via different streams
       
  1668 	CleanupClosePushL(rdStrm);
       
  1669 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"), TheDb1.LastInsertedRowId() - 1);
       
  1670 
       
  1671 	RSqlBlobReadStream rdStrm2;
       
  1672 	CleanupClosePushL(rdStrm2);
       
  1673 	rdStrm2.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1674 
       
  1675 	rdStrm.ReadL(data, 2);
       
  1676 	TEST(data.Compare(_L8("AB")) == 0);		
       
  1677 	rdStrm2.ReadL(data, 3);
       
  1678 	TEST(data.Compare(_L8("CDC")) == 0);	
       
  1679 	rdStrm.ReadL(data, 15);
       
  1680 	TEST(data.Compare(_L8("ABABABABABABEFE")) == 0);		
       
  1681 	rdStrm2.ReadL(data, 2);
       
  1682 	TEST(data.Compare(_L8("DC")) == 0);	
       
  1683 	CleanupStack::PopAndDestroy(2); 
       
  1684 	
       
  1685 	// Handles on the same blob
       
  1686 	// NOTE: using different stream objects on the same blob is only
       
  1687 	// safe when all of the stream objects are read streams - writing to 
       
  1688 	// the same blob from different streams or writing and reading from 
       
  1689 	// the same blob at the same time has undefined behaviour
       
  1690 	
       
  1691 	// Read from the same blob (blob2) via different streams
       
  1692 	CleanupClosePushL(wrStrm);
       
  1693 	wrStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1694 	wrStrm.WriteL(_L8("MNOPQR"));
       
  1695 	CleanupStack::PopAndDestroy(); // the blob2 update is committed 
       
  1696 
       
  1697 	CleanupClosePushL(rdStrm);
       
  1698 	rdStrm.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1699 
       
  1700 	CleanupClosePushL(rdStrm2);
       
  1701 	rdStrm2.OpenL(TheDb1, _L("table1"), _L("B"));
       
  1702 
       
  1703 	rdStrm.ReadL(data, 2);
       
  1704 	TEST(data.Compare(_L8("MN")) == 0);		
       
  1705 	rdStrm2.ReadL(data, 3);
       
  1706 	TEST(data.Compare(_L8("MNO")) == 0);	
       
  1707 	rdStrm.ReadL(data, 10);
       
  1708 	TEST(data.Compare(_L8("OPQRZZZZZZ")) == 0);		
       
  1709 	rdStrm2.ReadL(data, 15);
       
  1710 	TEST(data.Compare(_L8("PQRZZZZZZZZZZZZ")) == 0);	
       
  1711 	CleanupStack::PopAndDestroy(2); 
       
  1712 	}
       
  1713 	
       
  1714 void UTF16TextL(TInt aTextSize)
       
  1715 	{
       
  1716 	// The text value is "test", size 8 bytes in UTF-16, aTextSize = 8
       
  1717 	
       
  1718 	// Try to get the whole content of the text as UTF-8, using TSqlBlob::GetLC()
       
  1719 	HBufC8* wholeBuf = TSqlBlob::GetLC(TheDb1, _L("table1"), _L("T"));
       
  1720 	TInt bufSize = wholeBuf->Size(); // get the number of bytes in the buffer
       
  1721 	TEST2(bufSize, aTextSize);
       
  1722 	CleanupStack::PopAndDestroy(wholeBuf); 
       
  1723 	
       
  1724 	// Try to get the whole content of the text as UTF-8, using TSqlBlob::Get()
       
  1725 	HBufC8* buf = HBufC8::NewLC(aTextSize);	
       
  1726 	TPtr8 bufPtr(buf->Des());	  
       
  1727 	TInt err = TSqlBlob::Get(TheDb1, _L("table1"), _L("T"), bufPtr);
       
  1728 	TEST2(err, KErrNone); 
       
  1729 	bufSize = buf->Size(); // get the number of bytes in the buffer
       
  1730 	TEST2(bufSize, aTextSize);
       
  1731 	CleanupStack::PopAndDestroy(buf); 
       
  1732 
       
  1733 	// Try to set the whole content of the text as UTF-8, using TSqlBlob::SetL()
       
  1734 	HBufC8* dataBuf = HBufC8::NewLC(aTextSize);
       
  1735 	TPtr8 dataPtr(dataBuf->Des());
       
  1736 	dataPtr.Append(_L8("OPOPOPOP"));
       
  1737 	TRAP(err, TSqlBlob::SetL(TheDb1, _L("table1"), _L("T"), dataPtr));
       
  1738 	TEST2(err, KErrNone); // can set 8 UTF-8 characters as this is 8 bytes
       
  1739 	CleanupStack::PopAndDestroy(dataBuf); 	
       
  1740 	}
       
  1741 
       
  1742 /**
       
  1743 @SYMTestCaseID			SYSLIB-SQL-UT-4112
       
  1744 @SYMTestCaseDesc		UTF-16 text read and write tests using the UTF-8 methods of 
       
  1745 						TSqlBlob.
       
  1746 @SYMTestPriority		Medium
       
  1747 @SYMTestActions			Execution of UTF-16 text read and write operations using 
       
  1748 						UTF-8 descriptors.
       
  1749 @SYMTestExpectedResults Test must not fail
       
  1750 @SYMREQ					REQ10411
       
  1751                         REQ10418
       
  1752 */
       
  1753 void UTF16FormatTestL()
       
  1754 	{	
       
  1755 	// Insert a record with a UTF-16 text value (text is encoded in UTF-16 by default) 
       
  1756 	TInt err = TheDb1.Exec(_L("INSERT INTO table1 VALUES(1, 'test', x'46474647464746474647')"));
       
  1757 	TEST2(err, 1);
       
  1758 	const TInt KTextSize = 8; // 8 bytes (4 UTF-16 characters)
       
  1759 	
       
  1760 	// Now read and write the UTF-16 text value using UTF-8 methods
       
  1761 	UTF16TextL(KTextSize);	
       
  1762 	}
       
  1763 	
       
  1764 /**
       
  1765 @SYMTestCaseID			SYSLIB-SQL-UT-4114
       
  1766 @SYMTestCaseDesc		Storing a big blob test, to ensure that by using the methods 
       
  1767 						of RSqlBlobReadStream and RSqlBlobWriteStream larger blobs can 
       
  1768 						be stored in practice than in previous versions of Symbian SQL.
       
  1769 						Creates a 18Mb zeroblob and then writes data into it and reads
       
  1770 						the data back.
       
  1771 						Also tests the TSqlBlob APIs to store and retrieve a large blob.
       
  1772 						Note that the test will use 18Mb blob only in WINSCW builds.
       
  1773 						Otherwise the used blob size is 3Mb.
       
  1774 @SYMTestPriority		Medium
       
  1775 @SYMTestActions			Execution of creating a 18Mb zeroblob, writing data to it and 
       
  1776 						reading it back.
       
  1777 @SYMTestExpectedResults Test must not fail
       
  1778 @SYMREQ					REQ10410
       
  1779 */
       
  1780 void BigBlobTestL()
       
  1781 	{
       
  1782 	// In this test we create a zeroblob big enough to hold a 18MB blob.
       
  1783 	// 18MB is larger than the server could previously read or write,
       
  1784 	// due to the server heap limit of 6MB (WINSCW builds).
       
  1785 	// This test will prove that a 18MB blob can be written and read
       
  1786 	// using the new APIs but not with the old APIs
       
  1787 		
       
  1788 #if defined __WINS__ ||	defined __WINSCW__
       
  1789 	const TInt KBigBlobSize = 18 * 1024 * 1024;
       
  1790 #else
       
  1791 	const TInt KBigBlobSize = 3 * 1024 * 1024;
       
  1792 #endif
       
  1793 		
       
  1794 	// Create a zeroblob big enough to hold a 36MB blob
       
  1795 	TInt err = TheDb2.Exec(_L("BEGIN"));
       
  1796 	TEST(err >= 0);
       
  1797 	
       
  1798 	RSqlStatement stmt;
       
  1799 	err = stmt.Prepare(TheDb2, _L("INSERT INTO table2 values(435, 'big blob test', :Val)"));
       
  1800 	TEST2(err, KErrNone);
       
  1801 	TInt paramIndex = stmt.ParameterIndex(_L(":Val"));
       
  1802 	TEST(paramIndex >= 0);	
       
  1803 	err = stmt.BindZeroBlob(paramIndex, KBigBlobSize);
       
  1804 	TEST2(err, KErrNone);
       
  1805 	err = stmt.Exec();	
       
  1806 	stmt.Close();
       
  1807 	if(err == KErrDiskFull)	
       
  1808 		{
       
  1809 		(void)TheDb2.Exec(_L("ROLLBACK"));
       
  1810 		TheTest.Printf(_L("==== The disk is full. The test cannot be completed!\r\n"));
       
  1811 		RFs fs;
       
  1812 		err = fs.Connect();
       
  1813 		if(err == KErrNone)
       
  1814 			{
       
  1815 			TVolumeInfo vinfo;
       
  1816 			err = fs.Volume(vinfo, EDriveC);
       
  1817 			if(err == KErrNone)
       
  1818 				{
       
  1819 				TheTest.Printf(_L("==== Free disk space=%d\r\n"), vinfo.iFree);
       
  1820 				}
       
  1821 			fs.Close();
       
  1822 			}
       
  1823 		return;	
       
  1824 		}
       
  1825 	TEST2(err, 1);
       
  1826 	
       
  1827 	/////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1828 	// Fill a buffer with KBigBlobSize/KBlobPartCnt bytes of data 
       
  1829 	// (the test application's heap may be too small to allocate a KBigBlobSize bytes buffer)
       
  1830     const TInt KBlobWrPartCnt = 16;// 1/16 part of the blob will be written at once using streaming API
       
  1831 	const TInt KBufferSize1 = KBigBlobSize / KBlobWrPartCnt;
       
  1832 	HBufC8* blobWrBuf = HBufC8::NewLC(KBufferSize1);
       
  1833 	TPtr8 blobWrChunk(blobWrBuf->Des());
       
  1834 	blobWrChunk.Fill('Z', KBufferSize1);	
       
  1835 	
       
  1836 	// Write KBigBlobSize bytes to the blob in the inserted record
       
  1837 	RSqlBlobWriteStream wrStrm;
       
  1838 	CleanupClosePushL(wrStrm);
       
  1839 	wrStrm.OpenL(TheDb2, _L("table2"), _L("blob"));
       
  1840 	TInt size = wrStrm.SizeL(); // check the blob's size
       
  1841 	TEST2(size, KBigBlobSize);
       
  1842 	for(TInt i1=0;i1<KBlobWrPartCnt;++i1)
       
  1843 	    {
       
  1844         TRAP(err, wrStrm.WriteL(blobWrChunk)); // write KBufferSize1 bytes of data
       
  1845         TEST2(err, KErrNone);
       
  1846 	    }
       
  1847 	wrStrm.CommitL();
       
  1848 	CleanupStack::PopAndDestroy(&wrStrm);
       
  1849 	
       
  1850 	err = TheDb2.Exec(_L("COMMIT"));
       
  1851 	TEST2(err, 1);
       
  1852 	
       
  1853     /////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1854 	// Read the big blob value back from the record in KBigBlobSize/6 chunks
       
  1855     const TInt KBlobRdPartCnt = 24;// 1/24 part of the blob will be read at once using streaming API
       
  1856 	const TInt KBufferSize2 = KBigBlobSize / KBlobRdPartCnt;
       
  1857 	HBufC8* blobRdBuf = HBufC8::NewLC(KBufferSize2);
       
  1858 	TPtr8 blobRdBufPtr(blobRdBuf->Des());
       
  1859 	RSqlBlobReadStream rdStrm;
       
  1860 	CleanupClosePushL(rdStrm);
       
  1861 	rdStrm.OpenL(TheDb2, _L("table2"), _L("blob"));
       
  1862 	size = rdStrm.SizeL(); // check the blob's size
       
  1863 	TEST2(size, KBigBlobSize);
       
  1864 	for(TInt i2=0;i2<KBlobRdPartCnt;++i2)
       
  1865 	    {
       
  1866         rdStrm.ReadL(blobRdBufPtr, KBufferSize2);
       
  1867         TEST(blobRdBufPtr.Compare(blobWrChunk.Left(KBufferSize2)) == 0); // check the first KBigBlobSize/KBlobRdPartCnt bytes
       
  1868 	    }
       
  1869 	TRAP(err, rdStrm.ReadL(blobRdBufPtr, 1));
       
  1870 	TEST2(err, KErrEof); // check that there is no more data to be read
       
  1871 	CleanupStack::PopAndDestroy(2, blobRdBuf); // rdStrm, blobRdBuf
       
  1872 		
       
  1873     /////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1874 	// Try to read the whole KBigBlobSize blob value using the old API
       
  1875 	err = stmt.Prepare(TheDb2, _L("SELECT blob FROM table2 WHERE ROWID == :Val"));
       
  1876 	TEST2(err, KErrNone);
       
  1877 	paramIndex = stmt.ParameterIndex(_L(":Val"));
       
  1878 	TEST(paramIndex >= 0);	
       
  1879 	err = stmt.BindInt(paramIndex, TheDb2.LastInsertedRowId());
       
  1880 	TEST2(err, KErrNone);
       
  1881 	// Check that the blob retrieval fails (because there is
       
  1882 	// not enough server-side memory to load it into the VDBE)
       
  1883 	err = stmt.Next();
       
  1884 #if defined __WINS__ ||	defined __WINSCW__
       
  1885 	TEST2(err, KErrNoMemory);
       
  1886 #else	
       
  1887 	TEST2(err, KSqlAtRow);
       
  1888 #endif
       
  1889 	stmt.Close();
       
  1890 	
       
  1891     /////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1892 	// Try to write another KBigBlobSize bytes big blob value using the old API.
       
  1893     // Check that the at some point the blob write fails (because there is
       
  1894     // not enough server-side memory to store the whole KBigBlobSize bytes).
       
  1895 	err = stmt.Prepare(TheDb2, _L("INSERT INTO table2 values(99, 'text', :Val)"));
       
  1896 	TEST2(err, KErrNone);	
       
  1897 	paramIndex = stmt.ParameterIndex(_L(":Val"));
       
  1898 	TEST(paramIndex >= 0);
       
  1899 	RSqlParamWriteStream strm;
       
  1900 	err = strm.BindBinary(stmt, paramIndex);
       
  1901 	TEST2(err, KErrNone);
       
  1902 	for(TInt i3=0;i3<KBlobWrPartCnt && err==KErrNone;++i3)
       
  1903 	    {
       
  1904 	    TRAP(err, strm.WriteL(blobWrChunk, KBufferSize1)); 
       
  1905 	    }
       
  1906 #if defined __WINS__ ||	defined __WINSCW__
       
  1907 	TEST2(err, KErrNoMemory);
       
  1908 #else	
       
  1909 	TEST2(err, KErrNone);
       
  1910 #endif
       
  1911 	strm.Close();
       
  1912 	stmt.Close();
       
  1913 	CleanupStack::PopAndDestroy(blobWrBuf);
       
  1914 	blobWrBuf = NULL;
       
  1915 
       
  1916     /////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1917 	// Use the TSqlBlob APIs to insert another big blob of size 85Kb
       
  1918 	// (to test the block algorithm used by TSqlBlob 'set')
       
  1919 	const TInt KBigBlobSize2 = 85 * 1024;
       
  1920 	err = TheDb2.Exec(_L("BEGIN"));
       
  1921     TEST(err >= 0);
       
  1922 	
       
  1923 	err = stmt.Prepare(TheDb2, _L("INSERT INTO table2 values(189, 'another big blob', :Val)"));
       
  1924 	TEST2(err, KErrNone);
       
  1925 	paramIndex = stmt.ParameterIndex(_L(":Val"));
       
  1926 	TEST(paramIndex >= 0);	
       
  1927 	err = stmt.BindZeroBlob(paramIndex, KBigBlobSize2);
       
  1928 	TEST2(err, KErrNone);
       
  1929 	err = stmt.Exec();	
       
  1930 	TEST2(err, 1);
       
  1931 	stmt.Close();
       
  1932 
       
  1933 	blobWrBuf = HBufC8::NewLC(KBigBlobSize2);
       
  1934 	blobWrChunk.Set(blobWrBuf->Des());
       
  1935 	blobWrChunk.SetLength(KBigBlobSize2);
       
  1936     blobWrChunk.Fill('F');
       
  1937     TPtr8 p((TUint8*)blobWrChunk.Ptr() + blobWrChunk.Length() / 2, blobWrChunk.Length() / 2);
       
  1938     p.Fill('E');// blobWrBuf now contains 42.5Kb of 'E's followed by 42.5Kb of 'F's
       
  1939 
       
  1940 	TRAP(err, TSqlBlob::SetL(TheDb2, _L("table2"), _L("blob"), blobWrChunk));
       
  1941 	TEST2(err, KErrNone);
       
  1942 	
       
  1943 	err = TheDb2.Exec(_L("COMMIT"));
       
  1944 	TEST2(err, 1);
       
  1945 
       
  1946 	// Read the blob value back from the record	
       
  1947 	// (to test the block algorithm used by TSqlBlob 'get')
       
  1948 	HBufC8* buf = TSqlBlob::GetLC(TheDb2, _L("table2"), _L("blob"));
       
  1949 	TEST(buf->Des().Compare(blobWrChunk) == 0);
       
  1950     CleanupStack::PopAndDestroy(buf);
       
  1951     buf = NULL;
       
  1952 	
       
  1953 	buf = HBufC8::NewLC(KBigBlobSize2);
       
  1954 	blobRdBufPtr.Set(buf->Des());
       
  1955 	err = TSqlBlob::Get(TheDb2, _L("table2"), _L("blob"), blobRdBufPtr);	
       
  1956 	TEST2(err, KErrNone);
       
  1957 	TEST(blobRdBufPtr.Compare(blobWrChunk) == 0);
       
  1958 	
       
  1959 	CleanupStack::PopAndDestroy(2, blobWrBuf); // buf, blobWrBuf
       
  1960 	}
       
  1961 	
       
  1962 void DoTestsL()
       
  1963 	{	
       
  1964 	CreateTestDbs();
       
  1965 
       
  1966 	// Insert a zeroblob using RSqlStatement::BindZeroBlob() and read and write to it using streams
       
  1967 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4099: Stream BindZeroBlob() test"));
       
  1968 	StreamBindZeroBlobTestL();
       
  1969 			
       
  1970 	// Insert a zeroblob using SQLite's zeroblob() function and read and write to it using streams
       
  1971 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4100: Stream zeroblob() test"));
       
  1972 	StreamSqliteZeroBlobTestL();
       
  1973 		
       
  1974 	// Insert a record containing a 'real' blob and read and write to it using streams
       
  1975 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4101: Stream real blob test"));
       
  1976 	StreamRealBlobTestL();
       
  1977 	
       
  1978 	// Get a whole blob object
       
  1979 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4102: Whole value blob retrieval test"));
       
  1980 	GetWholeBlob3L();
       
  1981 		
       
  1982 	// Set a whole blob object
       
  1983 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4104: Whole value blob set test"));
       
  1984 	SetWholeBlob3L();
       
  1985 		
       
  1986 	// Attached database test
       
  1987 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4106: Attached database test"));
       
  1988 	AttachDbTestL();
       
  1989 	
       
  1990 	// Bad parameter test
       
  1991 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4107: Bad parameter test"));
       
  1992 	BadParamTestL();
       
  1993 	
       
  1994 	// Indexed column test
       
  1995 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4108: Indexed column test"));
       
  1996 	IndexedColumnTestL();
       
  1997 	
       
  1998 	// End Of File test
       
  1999 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4109: Eof test"));
       
  2000 	EofTestL();
       
  2001 	
       
  2002 	// Private secure database test
       
  2003 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4110: Private secure db test"));	
       
  2004 	PrivateSecureDbTestL();
       
  2005 	
       
  2006 	// Concurrent read and write test
       
  2007 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4111: Concurrent read and write test"));	
       
  2008 	ConcurrentReadAndWriteTestL();
       
  2009 	
       
  2010 	// UTF-16 read and write test
       
  2011 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4112: UTF-16 format test"));	
       
  2012 	UTF16FormatTestL();
       
  2013 	
       
  2014 	// Big blob test
       
  2015 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4114: Big blob test"));
       
  2016 	BigBlobTestL();
       
  2017 		
       
  2018 	DeleteTestDbs();
       
  2019 	}
       
  2020 
       
  2021 TInt E32Main()
       
  2022 	{
       
  2023 	TheTest.Title();
       
  2024 	
       
  2025 	CTrapCleanup* tc = CTrapCleanup::New();
       
  2026 	
       
  2027 	__UHEAP_MARK;
       
  2028 		
       
  2029 	CreateTestDir();
       
  2030 	DeleteTestDbs();
       
  2031 	FillLargeDataBuf();
       
  2032 	TRAPD(err, DoTestsL());
       
  2033 	TEST2(err, KErrNone);
       
  2034 
       
  2035 	__UHEAP_MARKEND;
       
  2036 	
       
  2037 	TheTest.End();
       
  2038 	TheTest.Close();
       
  2039 	
       
  2040 	delete tc;
       
  2041 
       
  2042 	User::Heap().Check();
       
  2043 	return KErrNone;
       
  2044 	}
       
  2045