Răsfoiți Sursa

2006-04-07 Senganal T <[email protected]>

	* Test/ProviderTests/System.Data.SqlClient/SqlCommandBuilderTest.cs :
		- Corrected the testcase to check for queries corresponding to
		ms.net 2.0
		- verify that columns that do not allow nulls are not included
		in the null-checks.
		- Added testcase to check for DBConcurrencyException for
		Delete Command. 
		- Check the DataType of the null-check parameters
	* System.Data.Common/DbDataAdapter.cs :
		* Update () : If the Update/Delete Query has a null check,
		then populate the parameter value correctly.
	*  System.Data.SqlClient/SqlCommandBuilder.cs :
		* CreateDeleteCommand () 
		* CreateUpdateCommand () 
		* CreateInsertCommand () 
			- Changed the signature. Do not need DataRow parameter 
			as the Query generated is parametric.
			- Correct the null-check term in the WhereClause, set the
			correct properties for null-check parameter
			fixes #78027
			- Modified the generated query to match the query as
			generated by 2.0. We now ignore null-check in the
			whereclause if the Column does not allow nulls.
		* ctor () : Set QuotePrefix and QuoteSuffix for 2.0 profile
		* GetUpdateCommand ()
		* GetInsertCommand ()
		* GetDeleteCommand ()
			- Do not create new command everytime. Create only if
			not already created.
		* RefreshSchema : Reset the commands.


svn path=/trunk/mcs/; revision=59175
Senganal T 20 ani în urmă
părinte
comite
bd85b69021

+ 6 - 0
mcs/class/System.Data/System.Data.Common/ChangeLog

@@ -1,3 +1,9 @@
+2006-04-07  Senganal T <[email protected]>
+
+	* DbDataAdapter.cs :
+		* Update () : If the Update/Delete Query has a null check,
+		then populate the parameter value correctly.
+
 2006-03-20  Senganal T <[email protected]>
 
 	* DataAdapter.cs :

+ 10 - 2
mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs

@@ -961,20 +961,28 @@ namespace System.Data.Common {
 				try {
 					if (command != null) {
 						DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+						IDataParameter nullCheckParam = null;
 						foreach (IDataParameter parameter in command.Parameters) {
 							if ((parameter.Direction & ParameterDirection.Input) != 0) {
 								string dsColumnName = parameter.SourceColumn;
 								if (columnMappings.Contains(parameter.SourceColumn))
 									dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-								if (dsColumnName == null || dsColumnName.Length <= 0)
+								if (dsColumnName == null || dsColumnName.Length <= 0) {
+									nullCheckParam = parameter;
 									continue;
-								
+								}
+
 								DataRowVersion rowVersion = parameter.SourceVersion;
 								// Parameter version is ignored for non-update commands
 								if (statementType == StatementType.Delete) 
 									rowVersion = DataRowVersion.Original;
 
 								parameter.Value = row [dsColumnName, rowVersion];
+								if (nullCheckParam != null && (parameter.Value != null
+									&& parameter.Value != DBNull.Value)) {
+									nullCheckParam.Value = 0;
+									nullCheckParam = null;
+								}
 							}
 						}
 					}

+ 22 - 0
mcs/class/System.Data/System.Data.SqlClient/ChangeLog

@@ -1,3 +1,25 @@
+2006-04-07  Senganal T  <[email protected]>
+
+	* SqlCommandBuilder.cs :
+		* CreateDeleteCommand () 
+		* CreateUpdateCommand () 
+		* CreateInsertCommand () 
+			- Changed the signature. Do not need DataRow parameter 
+			as the Query generated is parametric.
+			- Correct the null-check term in the WhereClause, set the
+			correct properties for null-check parameter
+			fixes #78027
+			- Modified the generated query to match the query as
+			generated by 2.0. We now ignore null-check in the
+			whereclause if the Column does not allow nulls.
+		* ctor () : Set QuotePrefix and QuoteSuffix for 2.0 profile
+		* GetUpdateCommand ()
+		* GetInsertCommand ()
+		* GetDeleteCommand ()
+			- Do not create new command everytime. Create only if
+			not already created.
+		* RefreshSchema : Reset the commands.
+
 2006-02-17  Chris Toshok  <[email protected]>
 
 	* SqlCommand.cs, SqlCommandBuilder.cs, SqlConnection.cs,

+ 49 - 76
mcs/class/System.Data/System.Data.SqlClient/SqlCommandBuilder.cs

@@ -71,8 +71,13 @@ namespace System.Data.SqlClient {
 		{
 			dbSchemaTable = null;
 			adapter = null;
+#if NET_2_0
+			quoteSuffix = "]";
+			quotePrefix = "[";
+#else
 			quoteSuffix = String.Empty;
 			quotePrefix = String.Empty;
+#endif
 		}
 
 		public SqlCommandBuilder (SqlDataAdapter adapter)
@@ -196,7 +201,7 @@ namespace System.Data.SqlClient {
 			dbSchemaTable = schemaTable;
 		}
 
-		private SqlCommand CreateDeleteCommand (DataRow row, DataTableMapping tableMapping) 
+		private SqlCommand CreateDeleteCommand ()
 		{
 			// If no table was found, then we can't do an delete
 			if (QuotedTableName == String.Empty)
@@ -223,42 +228,31 @@ namespace System.Data.SqlClient {
 				bool isKey = (bool) schemaRow ["IsKey"];
 				SqlParameter parameter = null;
 
-				if (!isKey) {
-					parameter = deleteCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
-					parameter.SourceVersion = DataRowVersion.Original;
+				if (isKey)
+					keyFound = true;
+
+				//ms.net 1.1 generates the null check for columns even if AllowDBNull is false
+				//while ms.net 2.0 does not. Anyways, since both forms are logically equivalent
+				//following the 2.0 approach
+				bool allowNull = (bool) schemaRow ["AllowDBNull"];
+				if (!isKey && allowNull) {
+					parameter = deleteCommand.Parameters.Add (String.Format ("@p{0}", parmIndex++),
+										SqlDbType.Int);
+					String sourceColumnName = (string) schemaRow ["BaseColumnName"];
+					parameter.Value = 1;
 
-					dsColumnName = parameter.SourceColumn;
-					if (tableMapping != null 
-					    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-						dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-				
-					if (row != null)
-						parameter.Value = row [dsColumnName, DataRowVersion.Original];
 					whereClause.Append ("(");
-					whereClause.Append (String.Format (clause1, parameter.ParameterName, GetQuotedString (parameter.SourceColumn)));
+					whereClause.Append (String.Format (clause1, parameter.ParameterName, 
+									GetQuotedString (sourceColumnName)));
 					whereClause.Append (" OR ");
 				}
-				else
-					keyFound = true;
-					
+
 				parameter = deleteCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
 				parameter.SourceVersion = DataRowVersion.Original;
 
-				dsColumnName = parameter.SourceColumn;
-				if (tableMapping != null 
-				    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-					dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-
-				if (row != null) {
-					if (row[dsColumnName, DataRowVersion.Original] == null || row[dsColumnName, DataRowVersion.Original] == DBNull.Value)
-						parameter.Value = 1;
-					else
-						parameter.Value = 0;
-				}
-
 				whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
 
-				if (!isKey)
+				if (!isKey && allowNull)
 					whereClause.Append (")");
 			}
 			if (!keyFound)
@@ -270,7 +264,7 @@ namespace System.Data.SqlClient {
 			return deleteCommand;
 		}
 
-		private SqlCommand CreateInsertCommand (DataRow row, DataTableMapping tableMapping) 
+		private SqlCommand CreateInsertCommand ()
 		{
 			if (QuotedTableName == String.Empty)
 				return null;
@@ -296,14 +290,6 @@ namespace System.Data.SqlClient {
 				SqlParameter parameter = insertCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
 				parameter.SourceVersion = DataRowVersion.Current;
 
-				dsColumnName = parameter.SourceColumn;
-				if (tableMapping != null 
-				    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-					dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-
-				if (row != null)
-					parameter.Value = row [dsColumnName];
-
 				columns.Append (GetQuotedString (parameter.SourceColumn));
 				values.Append (parameter.ParameterName);
 			}
@@ -326,7 +312,7 @@ namespace System.Data.SqlClient {
 			command.Parameters.Clear ();
 		}
 
-		private SqlCommand CreateUpdateCommand (DataRow row, DataTableMapping tableMapping) 
+		private SqlCommand CreateUpdateCommand ()
 		{
 			// If no table was found, then we can't do an update
 			if (QuotedTableName == String.Empty)
@@ -351,14 +337,6 @@ namespace System.Data.SqlClient {
 				SqlParameter parameter = updateCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
 				parameter.SourceVersion = DataRowVersion.Current;
 
-				dsColumnName = parameter.SourceColumn;
-				if (tableMapping != null 
-				    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-					dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-
-				if (row != null)
-					parameter.Value = row [dsColumnName];
-
 				columns.Append (String.Format ("{0} = {1}", GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
 			}
 
@@ -378,43 +356,29 @@ namespace System.Data.SqlClient {
 				SqlParameter parameter = null;
 
 
-				if (!isKey) {
-					parameter = updateCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
-					parameter.SourceVersion = DataRowVersion.Original;
-
-					dsColumnName = parameter.SourceColumn;
-					if (tableMapping != null 
-					    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-						dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-
-					if (row != null)
-						parameter.Value = row [dsColumnName, DataRowVersion.Original];
+				if (isKey)
+					keyFound = true;
 
+				//ms.net 1.1 generates the null check for columns even if AllowDBNull is false
+				//while ms.net 2.0 does not. Anyways, since both forms are logically equivalent
+				//following the 2.0 approach
+				bool allowNull = (bool) schemaRow ["AllowDBNull"];
+				if (!isKey && allowNull) {
+					parameter = updateCommand.Parameters.Add (String.Format ("@p{0}", parmIndex++),
+										SqlDbType.Int);
+					parameter.Value = 1;
 					whereClause.Append ("(");
-					whereClause.Append (String.Format (clause1, parameter.ParameterName, GetQuotedString (parameter.SourceColumn)));
+					whereClause.Append (String.Format (clause1, parameter.ParameterName,
+									GetQuotedString ((string) schemaRow ["BaseColumnName"])));
 					whereClause.Append (" OR ");
 				}
-				else
-					keyFound = true;
 					
 				parameter = updateCommand.Parameters.Add (CreateParameter (parmIndex++, schemaRow));
 				parameter.SourceVersion = DataRowVersion.Original;
 
-				dsColumnName = parameter.SourceColumn;
-				if (tableMapping != null 
-				    && tableMapping.ColumnMappings.Contains (parameter.SourceColumn))
-					dsColumnName = tableMapping.ColumnMappings [parameter.SourceColumn].DataSetColumn;
-
-				if (row != null) {
-					if (row[dsColumnName, DataRowVersion.Original] == null || row[dsColumnName, DataRowVersion.Original] == DBNull.Value)
-						parameter.Value = 1;
-					else
-						parameter.Value = 0;
-				}
-
 				whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
 
-				if (!isKey)
+				if (!isKey && allowNull)
 					whereClause.Append (")");
 			}
 			if (!keyFound)
@@ -465,7 +429,9 @@ namespace System.Data.SqlClient {
                 SqlCommand GetDeleteCommand ()
 		{
 			BuildCache (true);
-			return CreateDeleteCommand (null, null);
+			if (deleteCommand == null)
+				return CreateDeleteCommand ();
+			return deleteCommand;
 		}
 
 		public 
@@ -475,7 +441,9 @@ namespace System.Data.SqlClient {
                 SqlCommand GetInsertCommand ()
 		{
 			BuildCache (true);
-			return CreateInsertCommand (null, null);
+			if (insertCommand == null)
+				return CreateInsertCommand ();
+			return insertCommand;
 		}
 
 		private string GetQuotedString (string value)
@@ -494,7 +462,9 @@ namespace System.Data.SqlClient {
                 SqlCommand GetUpdateCommand ()
 		{
 			BuildCache (true);
-			return CreateUpdateCommand (null, null);
+			if (updateCommand == null)
+				return CreateUpdateCommand ();
+			return updateCommand;
 		}
 
 		private bool IncludedInInsert (DataRow schemaRow)
@@ -550,6 +520,9 @@ namespace System.Data.SqlClient {
 		{
 			tableName = String.Empty;
 			dbSchemaTable = null;
+			CreateNewCommand (ref deleteCommand);
+			CreateNewCommand (ref updateCommand);
+			CreateNewCommand (ref insertCommand);
 		}
 
 #if NET_2_0

+ 11 - 0
mcs/class/System.Data/Test/ProviderTests/System.Data.SqlClient/ChangeLog

@@ -1,3 +1,14 @@
+2006-04-07  Senganal T  <[email protected]>
+
+	* SqlCommandBuilderTest.cs :
+		- Corrected the testcase to check for queries corresponding to
+		ms.net 2.0
+		- verify that columns that do not allow nulls are not included
+		in the null-checks.
+		- Added testcase to check for DBConcurrencyException for
+		Delete Command. 
+		- Check the DataType of the null-check parameters
+
 2006-03-08  Senganal T  <[email protected]>
 
 	* SqlCommandBuilderTest.cs :

+ 63 - 9
mcs/class/System.Data/Test/ProviderTests/System.Data.SqlClient/SqlCommandBuilderTest.cs

@@ -89,7 +89,7 @@ namespace MonoTests.System.Data
 		{
 			IDbConnection conn = ConnectionManager.Singleton.Connection;
 			try {
-				string selectQuery = "select id, fname, id+1 as next_id from employee where id = 1";
+				string selectQuery = "select id, fname, lname, id+1 as next_id from employee where id = 1";
 				SqlDataAdapter da = new SqlDataAdapter (selectQuery, (SqlConnection) conn);
 				DataSet ds = new DataSet ();
 				da.Fill (ds, "IntTest");
@@ -97,13 +97,13 @@ namespace MonoTests.System.Data
 
 				SqlCommandBuilder cb = new SqlCommandBuilder (da);
 				SqlCommand cmd = cb.GetUpdateCommand ();
-				Assert.AreEqual ("UPDATE employee SET id = @p1, fname = @p2 WHERE ((id = @p3) AND ((@p4 = 1 AND fname IS NULL) OR (fname = @p5)))",
+				Assert.AreEqual ("UPDATE employee SET id = @p1, fname = @p2, lname = @p3 WHERE ((id = @p4)" +
+						" AND (fname = @p5) AND ((@p6 = 1 AND lname IS NULL) OR (lname = @p7)))",
 						cmd.CommandText, "#2");
-				Assert.AreEqual (5, cmd.Parameters.Count, "#3");
+				Assert.AreEqual (7, cmd.Parameters.Count, "#3");
 			} finally {
 				ConnectionManager.Singleton.CloseConnection ();
 			}
-
 		}
 
 		[Test]
@@ -125,14 +125,44 @@ namespace MonoTests.System.Data
 
 				SqlCommandBuilder cb = new SqlCommandBuilder (da);
 				SqlCommand updateCmd = cb.GetUpdateCommand ();
-				Assert.AreEqual ("UPDATE #tmp_table SET id = @p1, value = @p2 WHERE ((id = @p3) AND ((@p4 = 1 AND " +
-							"counter IS NULL) OR (counter = @p5)) AND ((@p6 = 1 AND value IS NULL) OR (value = @p7)))",
+				Assert.AreEqual ("UPDATE #tmp_table SET id = @p1, value = @p2 WHERE ((id = @p3) AND (" +
+							"counter = @p4) AND ((@p5 = 1 AND value IS NULL) OR (value = @p6)))",
 						updateCmd.CommandText, "#3");
-				Assert.AreEqual (7, updateCmd.Parameters.Count, "#3");
+				Assert.AreEqual (6, updateCmd.Parameters.Count, "#4");
+
+				SqlCommand delCmd = cb.GetDeleteCommand ();
+				Assert.AreEqual ("DELETE FROM #tmp_table WHERE ((id = @p1) AND (counter = @p2) AND " +
+						"((@p3 = 1 AND value IS NULL) OR (value = @p4)))", delCmd.CommandText, "#5");
+				Assert.AreEqual (4, delCmd.Parameters.Count, "#6");
+			} finally {
+				ConnectionManager.Singleton.CloseConnection ();
+			}
+		}
+
+		[Test]
+		public void GetUpdateDeleteCommand_CheckParameters ()
+		{
+			IDbConnection conn = ConnectionManager.Singleton.Connection;
+			try {
+				ConnectionManager.Singleton.OpenConnection ();
+				SqlDataAdapter adapter = new SqlDataAdapter ("select id, type_varchar from string_family",
+								(SqlConnection)conn);
+				SqlCommandBuilder cb = new SqlCommandBuilder (adapter);
+
+				SqlCommand updateCommand = cb.GetUpdateCommand ();
+				Assert.AreEqual (5, updateCommand.Parameters.Count, "#1");
+				Assert.AreEqual (SqlDbType.Int, updateCommand.Parameters ["@p4"].SqlDbType, "#2");
+				Assert.AreEqual (1, updateCommand.Parameters ["@p4"].Value, "#3");
+
+				SqlCommand delCommand = cb.GetDeleteCommand ();
+				Assert.AreEqual (3, delCommand.Parameters.Count, "#4");
+				Assert.AreEqual (SqlDbType.Int, delCommand.Parameters ["@p2"].SqlDbType, "#5");
+				Assert.AreEqual (1, delCommand.Parameters ["@p2"].Value, "#6");
 			} finally {
 				ConnectionManager.Singleton.CloseConnection ();
 			}
 		}
+		
 		[Test]
 		[ExpectedException (typeof (DBConcurrencyException))]
 		public void GetUpdateCommandDBConcurrencyExceptionTest ()
@@ -157,13 +187,37 @@ namespace MonoTests.System.Data
 			}
 		}
 
+		[Test]
+		[ExpectedException (typeof (DBConcurrencyException))]
+		public void GetDeleteCommandDBConcurrencyExceptionTest ()
+		{
+			IDbConnection conn = ConnectionManager.Singleton.Connection;
+			try {
+				ConnectionManager.Singleton.OpenConnection ();
+				string selectQuery = "select id, fname from employee where id = 1";
+				SqlDataAdapter da = new SqlDataAdapter (selectQuery, (SqlConnection) conn);
+				DataSet ds = new DataSet ();
+				da.Fill (ds, "IntTest");
+				Assert.AreEqual (1, ds.Tables.Count, "#1 atleast one table should be filled");
+
+				SqlCommandBuilder cb = new SqlCommandBuilder (da);
+				DataRow [] rows = ds.Tables [0].Select ("id=1");
+				rows [0] [0] = 6660; // non existent 
+				ds.Tables [0].AcceptChanges (); // moves 6660 to original value
+				rows [0].Delete ();  // moves 6660 as search key into db table
+				da.Update (rows);
+			} finally {
+				ConnectionManager.Singleton.CloseConnection ();
+			}
+		}
+
 		[Test]
 		public void GetDeleteCommandTest ()
 		{
 			IDbConnection conn = ConnectionManager.Singleton.Connection;
 			try {
 				ConnectionManager.Singleton.OpenConnection ();
-				string selectQuery = "select id, fname, id+1 as next_id from employee where id = 1";
+				string selectQuery = "select id, fname, lname, id+1 as next_id from employee where id = 1";
 				SqlDataAdapter da = new SqlDataAdapter (selectQuery, (SqlConnection) conn);
 				DataSet ds = new DataSet ();
 				da.Fill (ds, "IntTest");
@@ -171,7 +225,7 @@ namespace MonoTests.System.Data
 
 				SqlCommandBuilder cb = new SqlCommandBuilder (da);
 				SqlCommand cmd = cb.GetDeleteCommand ();
-				Assert.AreEqual ("DELETE FROM employee WHERE ((id = @p1) AND ((@p2 = 1 AND fname IS NULL) OR (fname = @p3)))",
+				Assert.AreEqual ("DELETE FROM employee WHERE ((id = @p1) AND (fname = @p2) AND ((@p3 = 1 AND lname IS NULL) OR (lname = @p4)))",
 						cmd.CommandText, "#2");
 			} finally {
 				ConnectionManager.Singleton.CloseConnection ();