Bug #7399 IsDBNull is useless with SequentialAccess behavior
Submitted: 18 Dec 2004 8:30 Modified: 25 Feb 2005 23:07
Reporter: [ name withheld ] Email Updates:
Status: Can't repeat Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version: OS:Any (Any)
Assigned to: Reggie Burnett CPU Architecture:Any

[18 Dec 2004 8:30] [ name withheld ]
Description:
    The IsDBNull function is useless with SequentialAccess behavior because when it is called the field value is actually read and after that the value is inaccessible any more.

How to repeat:
MySqlReader reader = ...
if (!reader.IsDBNull(columnOrdinal))
{
    // the following will read the next column value
    int value = reader.GetInt32(columnOrdinal);  
}

Suggested fix:
I have changed the CommandResult this[int index] so that the next value is read only if the requested index is greater than seqColumn. In such way IsDBNull can read and check the value for DBNull but after that reader.GetInt32 can get the readed value.

public MySqlValue this[int index] 
{
   get 
   { 
      if (usingSequentialAccess)
      {
         if (index < seqColumn)
            throw new MySqlException("Invalid attempt to read a prior column using SequentialAccess");
         else
	if (index > seqColumn)
	{
	   while (seqColumn+1 < index)
	   {
                   driver.SkipField(values[seqColumn+1]);
                   seqColumn++;
                }

                values[index] = driver.ReadFieldValue(index, fields[index], values[index]);
	   seqColumn = index;
	}
          }

          return values[index];
      }
      set { values[index] = value; }
}
[26 Jan 2005 19:05] Jorge del Conde
Thanks for the bug report
[25 Feb 2005 23:07] Reggie Burnett
Not enough information was provided for us to be able
to handle this bug. Please re-read the instructions at
http://bugs.mysql.com/how-to-report.php

If you can provide more information, feel free to add it
to this bug and change the status back to 'Open'.

Thank you for your interest in MySQL.

Additional info:

I can't repeat this with 1.0.4.  What version of the connector are you using?  Here is the unit test that I have testing with.

		[Test()]
		public void SequentialAccessBehavior() 
		{
			execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')");

			MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn);
			MySqlDataReader reader = null;
			try 
			{
				reader = cmd.ExecuteReader( CommandBehavior.SequentialAccess );
				Assert.IsTrue( reader.Read() );
				Assert.IsFalse( reader.IsDBNull(0));
				int i = reader.GetInt32(0);
				string s = reader.GetString( 1 );
				Assert.AreEqual( "test1", s );

				// this next line should throw an exception
				i = reader.GetInt32( 0 );
				Assert.Fail( "This line should not execute" );
			}
			catch (MySqlException) { }
			catch (Exception ex) 
			{
				Assert.Fail( ex.Message );
			}
			finally 
			{
				if (reader != null) reader.Close();
			}
		}