From: Date: September 18 2006 5:27pm Subject: Connector/NET commit: r342 - in branches/1.0: TestSuite mysqlclient List-Archive: http://lists.mysql.com/commits/12138 X-Bug: 16884 Message-Id: <200609181527.k8IFRe1J014373@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/1.0/TestSuite/DataReaderTests.cs branches/1.0/TestSuite/MySql.Data.Tests.csproj branches/1.0/mysqlclient/datareader.cs Log: Bug #16884 Invalid DateTime Values from DataReader Fixed this by implementing check on all typesafe methods for null. Basically, you cannot call the typesafe methods on null columns. You should use .IsDbNull to check for null values. Modified: branches/1.0/TestSuite/DataReaderTests.cs =================================================================== --- branches/1.0/TestSuite/DataReaderTests.cs 2006-09-18 15:26:03 UTC (rev 341) +++ branches/1.0/TestSuite/DataReaderTests.cs 2006-09-18 15:27:39 UTC (rev 342) @@ -102,7 +102,7 @@ } } - [Test()] + [Test] public void TestNotReadingResultset() { for (int x=0; x < 10; x++) @@ -121,7 +121,7 @@ } } - [Test()] + [Test] public void GetBytes() { int len = 50000; @@ -184,7 +184,7 @@ } - [Test()] + [Test] public void TestSingleResultSetBehavior() { execSQL("INSERT INTO Test (id, name, b1) VALUES (1, 'Test1', NULL)"); @@ -201,7 +201,7 @@ reader.Close(); } - [Test()] + [Test] public void GetSchema() { string sql = "CREATE TABLE test2( " + @@ -237,7 +237,7 @@ execSQL("DROP TABLE IF EXISTS test2"); } - [Test()] + [Test] public void CloseConnectionBehavior() { execSQL("INSERT INTO Test(id,name) VALUES(1,'test')"); @@ -264,7 +264,7 @@ } } - [Test()] + [Test] public void SingleRowBehavior() { execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); @@ -301,7 +301,7 @@ } } - [Test()] + [Test] public void SingleRowBehaviorWithLimit() { execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); @@ -340,7 +340,7 @@ } } - [Test()] + [Test] public void SimpleSingleRow() { execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); @@ -366,42 +366,55 @@ } } - [Test()] + [Test] public void ConsecutiveNulls() { - execSQL("INSERT INTO Test (id, name) VALUES (1, 'Test')"); - execSQL("INSERT INTO Test (id, name) VALUES (2, NULL)"); - execSQL("INSERT INTO Test (id, name) VALUES (3, 'Test2')"); + execSQL("INSERT INTO Test (id, name, dt) VALUES (1, 'Test', NULL)"); + execSQL("INSERT INTO Test (id, name, dt) VALUES (2, NULL, now())"); + execSQL("INSERT INTO Test (id, name, dt) VALUES (3, 'Test2', NULL)"); - MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + MySqlCommand cmd = new MySqlCommand("SELECT id, name, dt FROM Test", conn); MySqlDataReader reader = null; try { reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual( 1, reader.GetValue(0) ); - Assert.AreEqual( "Test", reader.GetValue(1) ); - Assert.AreEqual( "Test", reader.GetString(1) ); + Assert.AreEqual(1, reader.GetValue(0)); + Assert.AreEqual("Test", reader.GetValue(1)); + Assert.AreEqual("Test", reader.GetString(1)); + Assert.AreEqual(DBNull.Value, reader.GetValue(2)); reader.Read(); - Assert.AreEqual( 2, reader.GetValue(0) ); - Assert.AreEqual( DBNull.Value, reader.GetValue(1) ); - Assert.AreEqual( null, reader.GetString(1) ); - reader.Read(); - Assert.AreEqual( 3, reader.GetValue(0) ); - Assert.AreEqual( "Test2", reader.GetValue(1) ); - Assert.AreEqual( "Test2", reader.GetString(1) ); - Assert.IsFalse( reader.Read() ); - Assert.IsFalse( reader.NextResult() ); + Assert.AreEqual(2, reader.GetValue(0)); + Assert.AreEqual(DBNull.Value, reader.GetValue(1)); + try + { + reader.GetString(1); + Assert.Fail("Should not get here"); + } + catch (Exception) { } + Assert.IsFalse(reader.IsDBNull(2)); + reader.Read(); + Assert.AreEqual(3, reader.GetValue(0)); + Assert.AreEqual("Test2", reader.GetValue(1)); + Assert.AreEqual("Test2", reader.GetString(1)); + Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + try + { + reader.GetMySqlDateTime(2); + Assert.Fail("Should not get here"); + } + catch (Exception) { } + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); } catch (Exception ex) { - Assert.Fail( ex.Message ); + Assert.Fail(ex.Message); } finally { if (reader != null) reader.Close(); } - } [Test()] @@ -557,7 +570,7 @@ } } - [Test()] + [Test] public void TestManyDifferentResultsets() { MySqlDataReader reader =null; Modified: branches/1.0/TestSuite/MySql.Data.Tests.csproj =================================================================== --- branches/1.0/TestSuite/MySql.Data.Tests.csproj 2006-09-18 15:26:03 UTC (rev 341) +++ branches/1.0/TestSuite/MySql.Data.Tests.csproj 2006-09-18 15:27:39 UTC (rev 342) @@ -75,9 +75,9 @@ prompt - + False - ..\bin\net-2.0\Debug\MySql.Data.dll + ..\mysqlclient\bin\net-2.0\Debug\MySql.Data.dll nunit.framework Modified: branches/1.0/mysqlclient/datareader.cs =================================================================== --- branches/1.0/mysqlclient/datareader.cs 2006-09-18 15:26:03 UTC (rev 341) +++ branches/1.0/mysqlclient/datareader.cs 2006-09-18 15:27:39 UTC (rev 342) @@ -215,7 +215,7 @@ /// public byte GetByte(int i) { - MySqlValue v = GetFieldValue(i); + MySqlValue v = GetFieldValue(i, false); if (v is MySqlUByte) return ((MySqlUByte)v).Value; else @@ -237,7 +237,7 @@ if (i >= fields.Length) throw new IndexOutOfRangeException(); - MySqlValue val = GetFieldValue(i); + MySqlValue val = GetFieldValue(i, false); if (! (val is MySqlBinary)) throw new MySqlException("GetBytes can only be called on binary columns"); @@ -326,13 +326,13 @@ /// public MySqlDateTime GetMySqlDateTime(int index) { - return (MySqlDateTime)GetFieldValue(index); + return (MySqlDateTime)GetFieldValue(index, true); } /// public DateTime GetDateTime(int index) { - MySqlValue val = GetFieldValue(index); + MySqlValue val = GetFieldValue(index, true); if (val is MySqlDateTime) { MySqlDateTime dt = (MySqlDateTime)val; @@ -343,17 +343,17 @@ } else if (val is MySqlString) { - MySqlDateTime d = new MySqlDateTime( MySqlDbType.Datetime ); - d = d.ParseMySql( (val as MySqlString).Value, true ); + MySqlDateTime d = new MySqlDateTime(MySqlDbType.Datetime); + d = d.ParseMySql((val as MySqlString).Value, true); return d.GetDateTime(); } - throw new NotSupportedException( "Unable to convert from type " + val.GetType().ToString() + " to DateTime" ); + throw new NotSupportedException("Unable to convert from type " + val.GetType().ToString() + " to DateTime"); } /// public Decimal GetDecimal(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlDecimal) return ((MySqlDecimal)v).Value; return Convert.ToDecimal(v.ValueAsObject); @@ -362,7 +362,7 @@ /// public double GetDouble(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlDouble) return ((MySqlDouble)v).Value; return Convert.ToDouble(v.ValueAsObject); @@ -386,7 +386,7 @@ /// public float GetFloat(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlFloat) return ((MySqlFloat)v).Value; return Convert.ToSingle(v.ValueAsObject); @@ -401,7 +401,7 @@ /// public Int16 GetInt16(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlInt16) return ((MySqlInt16)v).Value; return Convert.ToInt16(v.ValueAsObject); @@ -410,7 +410,7 @@ /// public Int32 GetInt32(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlInt32) return ((MySqlInt32)v).Value; return Convert.ToInt32(v.ValueAsObject); @@ -419,7 +419,7 @@ /// public Int64 GetInt64(int index) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlInt64) return ((MySqlInt64)v).Value; return Convert.ToInt64(v.ValueAsObject); @@ -535,9 +535,7 @@ /// public String GetString(int index) { - MySqlValue val = GetFieldValue(index); - if (val.IsNull) - throw new SqlNullValueException(); + MySqlValue val = GetFieldValue(index, true); if (val is MySqlBinary) return (currentResult[index] as MySqlBinary).ToString(fields[index].Encoding); @@ -548,7 +546,7 @@ /// public TimeSpan GetTimeSpan(int index) { - MySqlTimeSpan ts = (MySqlTimeSpan)GetFieldValue(index); + MySqlTimeSpan ts = (MySqlTimeSpan)GetFieldValue(index, true); return ts.Value; } @@ -562,7 +560,7 @@ if (! isOpen) throw new Exception("No current query in data reader"); if (i >= fields.Length) throw new IndexOutOfRangeException(); - MySqlValue val = GetFieldValue(i); + MySqlValue val = GetFieldValue(i, false); if (val.IsNull) return DBNull.Value; // if the column is a date/time, then we return a MySqlDateTime @@ -599,7 +597,7 @@ /// public UInt16 GetUInt16( int index ) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlUInt16) return ((MySqlUInt16)v).Value; return Convert.ToUInt16(v.ValueAsObject); @@ -608,7 +606,7 @@ /// public UInt32 GetUInt32( int index ) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlUInt32) return ((MySqlUInt32)v).Value; return Convert.ToUInt32(v.ValueAsObject); @@ -617,7 +615,7 @@ /// public UInt64 GetUInt64( int index ) { - MySqlValue v = GetFieldValue(index); + MySqlValue v = GetFieldValue(index, true); if (v is MySqlUInt64) return ((MySqlUInt64)v).Value; return Convert.ToUInt64(v.ValueAsObject); @@ -746,7 +744,7 @@ } - private MySqlValue GetFieldValue(int index) + private MySqlValue GetFieldValue(int index, bool checkNull) { if (index < 0 || index >= fields.Length) throw new ArgumentException( "You have specified an invalid column ordinal." ); @@ -754,7 +752,10 @@ try { MySqlValue val = currentResult.ReadColumnValue(index); - if ( readCount == 0 ) + if (val.IsNull && checkNull) + throw new SqlNullValueException(); + + if (readCount == 0) throw new MySqlException("Invalid attempt to access a field before calling Read()"); return val;