List:Commits« Previous MessageNext Message »
From:Julio casal Date:April 8 2011 1:45pm
Subject:bzr commit into connector-net-6.2 branch (julio.casal:926)
View as plain text  
#At file:///C:/Users/jcasalt/Dev/connector-net/6.2/ based on revid:reggie.burnett@stripped

  926 Julio casal	2011-04-08 [merge]
      merged

    modified:
      CHANGES
      MySql.Data/Provider/Source/Connection.cs
      MySql.Data/Provider/Source/Driver.cs
      MySql.Data/Provider/Source/command.cs
      MySql.Data/Provider/Source/datareader.cs
      MySql.Data/Tests/Source/CommandTests.cs
      MySql.VisualStudio/MySql.VisualStudio.csproj
=== modified file 'CHANGES'
=== modified file 'CHANGES'
--- a/CHANGES	2011-03-09 18:18:40 +0000
+++ b/CHANGES	2011-04-08 13:45:19 +0000
@@ -33,6 +33,7 @@
   (MySQL bug #59346, Oracle bug #11766272)
 - small but important improvements in EF sql generation
 - added batching support for updates and deletes (bug #59616)
+- Introduced workaround to unexpected query aborts (server 5.1+) when executing a datareader after a command.Cancel() (MySQL bug#60541).
 
 Version 6.2.4
 - Fix authorization popup after modifying stored procedure in VS (Bug #44715)

=== modified file 'MySql.Data/Provider/Source/Connection.cs'
--- a/MySql.Data/Provider/Source/Connection.cs	2011-02-18 15:25:18 +0000
+++ b/MySql.Data/Provider/Source/Connection.cs	2011-04-08 13:45:19 +0000
@@ -51,6 +51,7 @@
         private bool hasBeenOpen;
         private SchemaProvider schemaProvider;
         private ProcedureCache procedureCache;
+        private bool isInUse;
 #if !CF
         private PerformanceMonitor perfMonitor;
 #endif
@@ -106,12 +107,11 @@
                 if (driver == null)
                     return null;
                 return driver.reader;
-
             }
-
             set 
             { 
                 driver.reader = value;
+                isInUse = driver.reader != null;
             }
         }
 
@@ -138,6 +138,12 @@
             }
         }
 
+        internal bool IsInUse
+        {
+            get{ return isInUse; }
+            set{ isInUse = value; }
+        }
+
         #endregion
 
         #region Properties
@@ -573,7 +579,11 @@
             }
             catch (Exception ex)
             {
-		MySqlTrace.LogWarning(ServerThread, String.Concat("Error occurred aborting the connection. Exception was: ", ex.Message));
+                MySqlTrace.LogWarning(ServerThread, String.Concat("Error occurred aborting the connection. Exception was: ", ex.Message));
+            }
+            finally
+            {
+                this.isInUse = false;
             }
             SetState(ConnectionState.Closed, true);
         }

=== modified file 'MySql.Data/Provider/Source/Driver.cs'
--- a/MySql.Data/Provider/Source/Driver.cs	2010-12-14 15:22:41 +0000
+++ b/MySql.Data/Provider/Source/Driver.cs	2011-04-08 13:45:19 +0000
@@ -336,6 +336,7 @@
             List<MySqlError> warnings = new List<MySqlError>();
 
             MySqlCommand cmd = new MySqlCommand("SHOW WARNINGS", connection);
+            cmd.InternallyCreated = true;
             using (MySqlDataReader reader = cmd.ExecuteReader())
             {
                 while (reader.Read())

=== modified file 'MySql.Data/Provider/Source/command.cs'
--- a/MySql.Data/Provider/Source/command.cs	2011-03-09 18:18:40 +0000
+++ b/MySql.Data/Provider/Source/command.cs	2011-04-08 13:45:19 +0000
@@ -58,11 +58,13 @@
 		internal Int64 lastInsertedId;
 		private PreparableStatement statement;
 		private int commandTimeout;
+        private bool canceled;
         private bool resetSqlSelect;
         List<MySqlCommand> batch;
         private string batchableCommandText;
         CommandTimer commandTimer;
         private bool useDefaultTimeout;
+        private bool internallyCreated;
 
 		/// <include file='docs/mysqlcommand.xml' path='docs/ctor1/*'/>
 		public MySqlCommand()
@@ -250,11 +252,22 @@
             get { return batch; }
         }
 
+        internal bool Canceled
+        {
+            get { return canceled; }
+        }
+
         internal string BatchableCommandText
         {
             get { return batchableCommandText; }
         }
 
+        internal bool InternallyCreated
+        {
+            get { return internallyCreated; }
+            set { internallyCreated = value; }
+        }
+
 		#endregion
 
 		#region Methods
@@ -268,6 +281,7 @@
         public override void Cancel()
         {
             connection.CancelQuery(connection.ConnectionTimeout);
+            canceled = true;
         }
 
 		/// <summary>
@@ -299,7 +313,7 @@
                 throw new InvalidOperationException("Connection must be valid and open.");
 
 			// Data readers have to be closed first
-			if (connection.Reader != null)
+            if (connection.IsInUse && !this.internallyCreated)
 				throw new MySqlException("There is already an open DataReader associated with this Connection which must be closed first.");
 
             if (CommandType == CommandType.StoredProcedure && !connection.driver.Version.isAtLeast(5, 0, 0))
@@ -359,7 +373,9 @@
             if (resetSqlSelect)
             {
                 resetSqlSelect = false;
-                new MySqlCommand("SET SQL_SELECT_LIMIT=DEFAULT", connection).ExecuteNonQuery();
+                MySqlCommand command = new MySqlCommand("SET SQL_SELECT_LIMIT=DEFAULT", connection);
+                command.internallyCreated = true;
+                command.ExecuteNonQuery();
             }
         }
 
@@ -451,6 +467,7 @@
             {
                 MySqlDataReader reader = new MySqlDataReader(this, statement, behavior);
                 connection.Reader = reader;
+                canceled = false;
                 // execute the statement
                 statement.Execute();
                 // wait for data to return
@@ -491,7 +508,6 @@
                     throw new MySqlException(ex.Message, true, ex);
                 }
 
-
                 // if we caught an exception because of a cancel, then just return null
                 if (ex.IsQueryAborted)
                     return null;

=== modified file 'MySql.Data/Provider/Source/datareader.cs'
--- a/MySql.Data/Provider/Source/datareader.cs	2010-12-14 15:22:41 +0000
+++ b/MySql.Data/Provider/Source/datareader.cs	2011-04-08 13:45:19 +0000
@@ -29,6 +29,7 @@
 using System.Collections.Generic;
 using System.Globalization;
 using MySql.Data.MySqlClient.Properties;
+using MySql.Data.Common;
 
 namespace MySql.Data.MySqlClient
 {
@@ -231,10 +232,17 @@
 			// stored procedures it needs to update out and inout parameters
 			command.Close(this);
 
+            if (this.command.Canceled && connection.driver.Version.isAtLeast(5, 1, 0))
+            {
+                // Issue dummy command to clear kill flag
+                ClearKillFlag();
+            }
+
 			if (shouldCloseConnection)
 				connection.Close();
 
 			command = null;
+            connection.IsInUse = false;
 			connection = null;
             isOpen = false;
 		}
@@ -972,6 +980,16 @@
 			return v;
 		}
 
+
+        private void ClearKillFlag()
+        {
+            // This query will silently crash because of the Kill call that happened before.
+            string dummyStatement = "SELECT * FROM bogus_table LIMIT 0"; /* dummy query used to clear kill flag */
+            MySqlCommand dummyCommand = new MySqlCommand(dummyStatement, connection);
+            dummyCommand.InternallyCreated = true;
+            IDataReader reader = dummyCommand.ExecuteReader(); // ExecuteReader catches the exception and returns null, which is expected.
+        }
+
 		#region IEnumerator
 
 		/// <summary>

=== modified file 'MySql.Data/Tests/Source/CommandTests.cs'
--- a/MySql.Data/Tests/Source/CommandTests.cs	2011-03-22 19:47:06 +0000
+++ b/MySql.Data/Tests/Source/CommandTests.cs	2011-04-08 13:45:19 +0000
@@ -537,6 +537,35 @@
             Assert.AreEqual(1, listener.Find("Query Opened: UPDATE"));
         }
 #endif
+
+        [Test]
+        public void ExecuteReaderReturnsReaderAfterCancel()
+        {
+            execSQL("DROP TABLE IF EXISTS TableWithDateAsPrimaryKey");
+            execSQL("DROP TABLE IF EXISTS TableWithStringAsPrimaryKey");
+            createTable("CREATE TABLE TableWithDateAsPrimaryKey(PrimaryKey date NOT NULL, PRIMARY KEY  (PrimaryKey))", "InnoDB");
+            createTable("CREATE TABLE TableWithStringAsPrimaryKey(PrimaryKey nvarchar(50) NOT NULL, PRIMARY KEY  (PrimaryKey))", "InnoDB");
+
+            string connStr = GetConnectionString(true);
+            using (MySqlConnection connection = new MySqlConnection(connStr))
+            {
+                connection.Open();
+                MySqlCommand command = new MySqlCommand("SELECT PrimaryKey FROM TableWithDateAsPrimaryKey", connection);
+                IDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo);
+                DataTable dataTableSchema = reader.GetSchemaTable();
+                command.Cancel();
+                reader.Close();
+
+                command = new MySqlCommand("SELECT PrimaryKey FROM TableWithStringAsPrimaryKey", connection);
+                reader = command.ExecuteReader(CommandBehavior.KeyInfo);
+                Assert.IsNotNull(reader);
+
+                dataTableSchema = reader.GetSchemaTable();
+                Assert.AreEqual("PrimaryKey", dataTableSchema.Rows[0][dataTableSchema.Columns[0]]);
+
+                reader.Close();
+            }
+        }
     }
 
 

=== modified file 'MySql.VisualStudio/MySql.VisualStudio.csproj'
--- a/MySql.VisualStudio/MySql.VisualStudio.csproj	2010-08-18 19:42:41 +0000
+++ b/MySql.VisualStudio/MySql.VisualStudio.csproj	2011-04-08 13:45:19 +0000
@@ -57,17 +57,11 @@
   <ItemGroup>
     <Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
     <Reference Include="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
-    <Reference Include="Microsoft.Data.ConnectionUI, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>True</SpecificVersion>
-      <HintPath>c:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Common\Assemblies\Microsoft.Data.ConnectionUI.dll</HintPath>
-    </Reference>
+    <Reference Include="Microsoft.Data.ConnectionUI, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="Microsoft.VisualStudio.CommandBars, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <SpecificVersion>True</SpecificVersion>
     </Reference>
-    <Reference Include="Microsoft.VisualStudio.Data, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>True</SpecificVersion>
-      <HintPath>c:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.Data.dll</HintPath>
-    </Reference>
+    <Reference Include="Microsoft.VisualStudio.Data, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <SpecificVersion>True</SpecificVersion>
       <HintPath>c:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.OLE.Interop.dll</HintPath>

No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).
Thread
bzr commit into connector-net-6.2 branch (julio.casal:926) Julio casal8 Apr