Browse Source

2003-11-08 Pedro Mart�nez Juli� <[email protected]>

    * Npgsql/NpgsqlCommandBuilder.cs: Added the command builder.

    * Npgsql/NpgsqlDataAdapter.cs: Added the CommandBuilder stuff. When
    OnRowUpdating is called we create the command necesary for updating,
    inserting or deleting any row of the DataTable/DataSet.

    * Npgsql/NpgsqlCommand.cs: Temporary try-catch. ResMan still doesn't
    work. This must be removed when ResMan works.

    * Npgsql/NpgsqlParameter: No more than one call to value.GetType()
    is more efficient for the deep if structure types.

svn path=/trunk/mcs/; revision=19730
Pedro Martínez Juliá 22 years ago
parent
commit
2fbf99acb8

+ 14 - 0
mcs/class/Npgsql/ChangeLog

@@ -1,3 +1,17 @@
+2003-11-08  Pedro Martínez Juliá  <[email protected]>
+
+	* Npgsql/NpgsqlCommandBuilder.cs: Added the command builder.
+
+	* Npgsql/NpgsqlDataAdapter.cs: Added the CommandBuilder stuff. When
+	OnRowUpdating is called we create the command necesary for updating,
+	inserting or deleting any row of the DataTable/DataSet.
+
+	* Npgsql/NpgsqlCommand.cs: Temporary try-catch. ResMan still doesn't
+	work. This must be removed when ResMan works.
+
+	* Npgsql/NpgsqlParameter: No more than one call to value.GetType()
+	is more efficient for the deep if structure types.
+
 2003-11-07  Pedro Martínez Juliá  <[email protected]>
 
 	* Npgsql/NpgsqlDataAdapter.cs: Fixed the mistake I did in the last

+ 1 - 0
mcs/class/Npgsql/Npgsql.dll.sources

@@ -8,6 +8,7 @@ Npgsql/NpgsqlBinaryRow.cs
 Npgsql/NpgsqlBind.cs
 Npgsql/NpgsqlClosedState.cs
 Npgsql/NpgsqlCommand.cs
+Npgsql/NpgsqlCommandBuilder.cs
 Npgsql/NpgsqlConnectedState.cs
 Npgsql/NpgsqlConnection.cs
 Npgsql/NpgsqlConnector.cs

+ 6 - 1
mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs

@@ -320,7 +320,12 @@ namespace Npgsql {
 			// Check if there were any errors.
 			if (connection.Mediator.Errors.Count > 0) {
 				StringWriter sw = new StringWriter();
-				sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteNonQuery"));
+				try {
+					sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteNonQuery"));
+				}
+				catch (System.Resources.MissingManifestResourceException mmre) {
+					sw.WriteLine(String.Format("Exception_MediatorErrors", "ExecuteNonQuery"));
+				}
 				uint i = 1;
 				foreach(string error in connection.Mediator.Errors){
 					sw.WriteLine("{0}. {1}", i++, error);

+ 208 - 0
mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs

@@ -0,0 +1,208 @@
+// NpgsqlCommandBuilder.cs
+//
+// Author:
+//   Pedro Martínez Juliá ([email protected])
+//
+// Copyright (C) 2003 Pedro Martínez Juliá
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+using System;
+using System.Data;
+using System.ComponentModel;
+
+namespace Npgsql {
+
+	public sealed class NpgsqlCommandBuilder : Component {
+		
+		bool disposed = false;
+
+		private NpgsqlDataAdapter data_adapter;
+		private NpgsqlCommand insert_command;
+		private NpgsqlCommand update_command;
+		private NpgsqlCommand delete_command;
+
+		private string table_name = String.Empty;
+
+		public NpgsqlCommandBuilder () {
+		}
+
+		public NpgsqlCommandBuilder (NpgsqlDataAdapter adapter) {
+			DataAdapter = adapter;
+		}
+
+		public NpgsqlDataAdapter DataAdapter {
+			get {
+				return data_adapter;
+			}
+			set {
+				if (data_adapter != null) {
+					throw new Exception ("DataAdapter is already set");
+				}
+				data_adapter = value;
+				string select_text = data_adapter.SelectCommand.CommandText;
+				string[] words = select_text.Split(new char [] {' '});
+				bool from_found = false;
+				for (int i = 0; i < words.Length; i++) {
+					if (from_found && (words[i] != String.Empty)) {
+						table_name = words[i];
+						break;
+					}
+					if (words[i].ToLower() == "from") {
+						from_found = true;
+					}
+				}
+			}
+		}
+
+		public string QuotePrefix {
+			get { return ""; }
+			set { }
+		}
+
+		public string QuoteSuffix {
+			get { return ""; }
+			set { }
+		}
+
+		public static void DeriveParameters (NpgsqlCommand command) {
+		}
+
+		public NpgsqlCommand GetInsertCommand (DataRow row) {
+			if (insert_command == null) {
+				string fields = "";
+				string values = "";
+				for (int i = 0; i < row.Table.Columns.Count; i++) {
+					DataColumn column = row.Table.Columns[i];
+					if (i != 0) {
+						fields += ", ";
+						values += ", ";
+					}
+					fields += column.ColumnName;
+					values += ":param_" + column.ColumnName;
+				}
+				if (table_name == String.Empty) {
+					table_name = row.Table.TableName;
+				}
+				NpgsqlCommand cmdaux = new NpgsqlCommand("insert into " + table_name + " (" + fields + ") values (" + values + ")", data_adapter.SelectCommand.Connection);
+				foreach (DataColumn column in row.Table.Columns) {
+					NpgsqlParameter aux = new NpgsqlParameter("param_" + column.ColumnName, row[column]);
+					aux.Direction = ParameterDirection.Input;
+					aux.SourceColumn = column.ColumnName;
+					cmdaux.Parameters.Add(aux);
+				}
+				insert_command = cmdaux;
+			}
+			return insert_command;
+		}
+
+		public NpgsqlCommand GetUpdateCommand (DataRow row) {
+			if (update_command == null) {
+				string sets = "";
+				string wheres = "";
+				for (int i = 0; i < row.Table.Columns.Count; i++) {
+					if (i != 0) {
+						sets += ", ";
+						wheres += " and ";
+					}
+					DataColumn column = row.Table.Columns[i];
+					sets += String.Format("{0} = :s_param_{0}", column.ColumnName);
+					wheres += String.Format("(({0} is null) or ({0} = :w_param_{0}))", column.ColumnName);
+				}
+				if (table_name == String.Empty) {
+					table_name = row.Table.TableName;
+				}
+				NpgsqlCommand cmdaux = new NpgsqlCommand("update " + table_name + " set " + sets + " where ( " + wheres + " )", data_adapter.SelectCommand.Connection);
+				foreach (DataColumn column in row.Table.Columns) {
+					NpgsqlParameter aux = new NpgsqlParameter("s_param_" + column.ColumnName, row[column]);
+					aux.Direction = ParameterDirection.Input;
+					aux.SourceColumn = column.ColumnName;
+					aux.SourceVersion = DataRowVersion.Current;
+					cmdaux.Parameters.Add(aux);
+				}
+				foreach (DataColumn column in row.Table.Columns) {
+					NpgsqlParameter aux = new NpgsqlParameter("w_param_" + column.ColumnName, row[column]);
+					aux.Direction = ParameterDirection.Input;
+					aux.SourceColumn = column.ColumnName;
+					aux.SourceVersion = DataRowVersion.Original;
+					cmdaux.Parameters.Add(aux);
+				}
+				update_command = cmdaux;
+
+			}
+			return update_command;
+		}
+
+		public NpgsqlCommand GetDeleteCommand (DataRow row) {
+			if (delete_command == null) {
+				string wheres = "";
+				for (int i = 0; i < row.Table.Columns.Count; i++) {
+					DataColumn column = row.Table.Columns[i];
+					if (i != 0) {
+						wheres += " and ";
+					}
+					wheres += String.Format("(({0} is null) or ({0} = :w_param_{0}", column.ColumnName);
+				}
+				if (table_name == String.Empty) {
+					table_name = row.Table.TableName;
+				}
+				NpgsqlCommand cmdaux = new NpgsqlCommand("delete from " + table_name + " where ( " + wheres + " )", data_adapter.SelectCommand.Connection);
+				foreach (DataColumn column in row.Table.Columns) {
+					NpgsqlParameter aux = new NpgsqlParameter("param_" + column.ColumnName, row[column]);
+					aux.Direction = ParameterDirection.Input;
+					aux.SourceColumn = column.ColumnName;
+					cmdaux.Parameters.Add(aux);
+				}
+				delete_command = cmdaux;
+			}
+			return delete_command;
+		}
+
+		public void RefreshSchema () {
+			insert_command = null;
+			update_command = null;
+			delete_command = null;
+		}
+
+		protected override void Dispose (bool disposing) {
+			if (!disposed) {
+				if (disposing) {
+					if (insert_command != null) {
+						insert_command.Dispose();
+					}
+					if (update_command != null) {
+						update_command.Dispose();
+					}
+					if (delete_command != null) {
+						delete_command.Dispose();
+					}
+				}
+			}
+		}
+
+		~NpgsqlCommandBuilder () {
+			Dispose(false);
+		}
+
+	}
+
+}
+

+ 26 - 2
mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs

@@ -38,6 +38,8 @@ namespace Npgsql
 		private NpgsqlCommand		_updateCommand;
 		private NpgsqlCommand		_deleteCommand;
 		private NpgsqlCommand		_insertCommand;
+
+		private NpgsqlCommandBuilder cmd_builder;
 		
 		// Log support
 		private static readonly String CLASSNAME = "NpgsqlDataAdapter";
@@ -48,6 +50,7 @@ namespace Npgsql
 		{
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
             _selectCommand = selectCommand;
+			cmd_builder = new NpgsqlCommandBuilder(this);
 		}
 		
 		public NpgsqlDataAdapter(String selectCommandText, NpgsqlConnection selectConnection) : this(new NpgsqlCommand(selectCommandText, selectConnection)){}
@@ -94,8 +97,29 @@ namespace Npgsql
 				)
 		{
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "OnRowUpdating");
-			//base.OnRowUpdating(value);
-			
+			switch (value.StatementType) {
+				case StatementType.Insert:
+					value.Command = _insertCommand = cmd_builder.GetInsertCommand(value.Row);
+					break;
+				case StatementType.Update:
+					value.Command = _updateCommand = cmd_builder.GetUpdateCommand(value.Row);
+					break;
+				case StatementType.Delete:
+					value.Command = _deleteCommand = cmd_builder.GetDeleteCommand(value.Row);
+					break;
+			}
+			DataColumnMappingCollection columnMappings = value.TableMapping.ColumnMappings;
+			foreach (IDataParameter parameter in value.Command.Parameters) {
+				
+				string dsColumnName = parameter.SourceColumn;
+				DataColumnMapping mapping = columnMappings [parameter.SourceColumn];
+				if (mapping != null) dsColumnName = mapping.DataSetColumn;
+				DataRowVersion rowVersion = DataRowVersion.Default;
+				if (value.StatementType == StatementType.Update) rowVersion = parameter.SourceVersion;
+				if (value.StatementType == StatementType.Delete) rowVersion = DataRowVersion.Original;
+				parameter.Value = value.Row [dsColumnName, rowVersion];
+			}
+			value.Row.AcceptChanges ();
 		}
 		
 		ITableMappingCollection IDataAdapter.TableMappings

+ 42 - 22
mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs

@@ -99,47 +99,67 @@ namespace Npgsql
 			// http://msdn.microsoft.com/library/en-us/cpguide/html/cpconusingparameterswithdataadapters.asp
 			// Should this be in this.Value.set{}?
 			//I don't really know so I leave it here where it will not hurt.
-			if(value == null){
-        // don't really know what to do - leave default and do further exploration
-			}else if(value.GetType() == typeof(bool)){
+			if (value == null) {
+		        // don't really know what to do - leave default and do further exploration
+				return;
+			}
+			Type type = value.GetType();
+			if (type == typeof(bool)) {
 				db_type = DbType.Boolean;
-			}else if(value.GetType() == typeof(byte)){
+			}
+			else if (type == typeof(byte)) {
 				db_type = DbType.Byte;
-			}else if(value.GetType() == typeof(byte[])){
+			}
+			else if (type == typeof(byte[])) {
 				db_type = DbType.Binary;
-			}else if(value.GetType() == typeof(char)){
+			}
+			else if (type == typeof(char)) {
 				// There is no DbType.Char
 				db_type = DbType.String;
-			}else if(value.GetType() == typeof(DateTime)){
+			}
+			else if (type == typeof(DateTime)) {
 				db_type = DbType.DateTime;
-			}else if(value.GetType() == typeof(decimal)){
+			}
+			else if (type == typeof(decimal)) {
 				db_type = DbType.Decimal;
-			}else if(value.GetType() == typeof(double)){
+			}
+			else if (type == typeof(double)) {
 				db_type = DbType.Double;
-			}else if(value.GetType() == typeof(float)){
+			}
+			else if (type == typeof(float)) {
 				db_type = DbType.Single;
-			}else if(value.GetType() == typeof(Guid)){
+			}
+			else if (type == typeof(Guid)) {
 				db_type = DbType.Guid;
-			}else if(value.GetType() == typeof(Int16)){
+			}
+			else if (type == typeof(Int16)) {
 				db_type = DbType.Int16;
-			}else if(value.GetType() == typeof(Int32)){
+			}
+			else if (type == typeof(Int32)) {
 				db_type = DbType.Int32;
-			}else if(value.GetType() == typeof(Int64)){
+			}
+			else if (type == typeof(Int64)) {
 				db_type = DbType.Int64;
-			}else if(value.GetType() == typeof(string)){
+			}
+			else if (type == typeof(string)) {
 				db_type = DbType.String;
-			}else if(value.GetType() == typeof(TimeSpan)){
+			}
+			else if (type == typeof(TimeSpan)) {
 				db_type = DbType.Time;
-			}else if(value.GetType() == typeof(UInt16)){
+			}
+			else if (type == typeof(UInt16)) {
 				db_type = DbType.UInt16;
-			}else if(value.GetType() == typeof(UInt32)){
+			}
+			else if (type == typeof(UInt32)) {
 				db_type = DbType.UInt32;
-			}else if(value.GetType() == typeof(UInt64)){
+			}
+			else if (type == typeof(UInt64)) {
 				db_type = DbType.UInt64;
-			}else if(value.GetType() == typeof(object)){
+			}
+			else if (type == typeof(object)) {
 				db_type = DbType.Object;
-			}else{
-				throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType().ToString()));
+			} else{
+				throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), type.ToString()));
 			}
 
 			this.value = value;