[Mono-bugs] [Bug 79004][Blo] New - ORACLE: Double-byte characters passed as parameters get trimmed

bugzilla-daemon at bugzilla.ximian.com bugzilla-daemon at bugzilla.ximian.com
Thu Aug 3 12:33:29 EDT 2006


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by bpatton at perseus.com.

http://bugzilla.ximian.com/show_bug.cgi?id=79004

--- shadow/79004	2006-08-03 12:33:29.000000000 -0400
+++ shadow/79004.tmp.24528	2006-08-03 12:33:29.000000000 -0400
@@ -0,0 +1,176 @@
+Bug#: 79004
+Product: Mono: Class Libraries
+Version: 1.1
+OS: RHEL 2.1
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Blocker
+Component: Sys.Data
+AssignedTo: tsenganal at novell.com                            
+ReportedBy: bpatton at perseus.com               
+QAContact: mono-bugs at ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: ORACLE: Double-byte characters passed as parameters get trimmed 
+
+Description of Problem:
+Using an OracleParameter with a string containing characters greater than a
+single byte causes the inserted value to be trimmed. It looks like the
+character counting is wrong and the string is trimmed by the number of
+extra bytes the double-byte characters take up. 
+
+The columns and paramters types are NCLOB and NVARCHAR2. NLS_LANG is set to
+American_America.UTF8 and all of the locale is set to UTF8.
+
+Steps to reproduce the problem:
+1. Compile and run the attached code below. 
+2. Open a viewer into the Oracle database (like Enterprise Manager) and
+view the MONO_TEST table.
+
+Actual Results:
+NUM_VALUE = 10
+Q2 = testing 日本 (Japan 
+TXT_VALUE = testing 日本 (Japan 
+
+Expected Results:
+NUM_VALUE = 10
+Q2 = testing 日本 (Japanese)
+TXT_VALUE = testing 日本 (Japanese) 
+
+How often does this happen? 
+Always
+
+Additional Information:
+
+using System;
+using System.Data;
+using System.Data.Common;
+using System.Data.OracleClient;
+ 
+namespace TestOracleClientAdapter {
+	public class Test {
+		static IDbConnection con;
+ 
+		public static void Main (string[] args) 
+		{
+			Console.WriteLine("Apapter Test Begin...");
+			string connectionString = "Server=prometheus.perseus.net;User
+ID=mono;Password=wombat81;";
+			using (con = new OracleConnection(connectionString)) {
+			    con.Open();
+			
+			    Setup();
+			    
+			    con.Close();
+			    con.Open();
+ 
+			    Insert();
+			}
+			Console.WriteLine("Done.");
+		}
+ 
+		static void Setup() 
+		{
+			using (IDbCommand cmd = con.CreateCommand()) {
+				cmd.CommandText = "DROP TABLE MONO_TEST";
+ 
+				try { 
+					cmd.ExecuteNonQuery(); 
+				} catch(OracleException e) { }
+ 
+				cmd.CommandText = 
+					"CREATE TABLE MONO_TEST (" +
+					" num_value int," +
+					" Q2 nclob," +
+					" txt_value nvarchar2(64))";
+				cmd.ExecuteNonQuery();
+			}
+		}
+ 
+		static void Insert() {
+		
+			Console.WriteLine("Insert...");
+			
+			IDbCommand cmd = GetDbCommand(con, 
+				"INSERT INTO MONO_TEST (num_value, Q2, txt_value) VALUES (?, ?, ?)");
+			//cmd.CommandText = "INSERT INTO MONO_TEST (num_value) VALUES (?);";
+			AddParameter(cmd, "num", 10);
+			AddParameter(cmd, "Q2", "testing 日本 (Japanese)");
+			AddParameter(cmd, "txt", "testing 日本 (Japanese)");
+Console.WriteLine("Command: " + cmd.CommandText);
+			cmd.ExecuteNonQuery();
+		}
+		
+		public static IDbCommand GetDbCommand(IDbConnection dbConnection, string
+sql) {
+			IDbCommand cmd = dbConnection.CreateCommand();
+
+			// For readability we break some of our SQL into multiple lines. 
+			// DB2 does not like this so remove the carriage return, line feeds.
+			string command = sql.Replace("\r\n", " ");
+
+			cmd.CommandText = command;
+			return cmd;
+		}
+		
+		/// <summary>
+		/// Add an int parameter to the db command.
+		/// </summary>
+		public static void AddParameter(IDbCommand cmd, string parameterName, int
+parameterValue) {
+			OracleParameter param = CreateSqlParameter(cmd, parameterName,
+OracleType.Int32);
+			param.Value = parameterValue;
+			cmd.Parameters.Add(param);
+		}
+
+		/// <summary>
+		/// Add a string paramter to the db command
+		/// </summary>
+		public static void AddParameter(IDbCommand cmd, string parameterName,
+string parameterValue) {
+			OracleParameter param = CreateSqlParameter(cmd, parameterName,
+OracleType.NVarChar);
+			param.Value = parameterValue;
+			cmd.Parameters.Add(param);
+		}
+
+		/// <summary>
+		/// Add a large string paramter to the db command
+		/// </summary>
+		public static void AddClobParameter(IDbCommand cmd, string parameterName,
+string parameterValue) {
+			OracleParameter param = CreateSqlParameter(cmd, parameterName,
+OracleType.NClob);
+
+			// ORA-01013: User requested cancel of current operation
+			// Oracle throws an error when attempting to insert an empty string into
+an NCLOB field. 
+			// As a workaround set the parameter to null value.
+			if (parameterValue == string.Empty) {
+				param.Value = null;
+			} else {
+				param.Value = parameterValue;
+			}
+			cmd.Parameters.Add(param);
+		}
+		
+		private static OracleParameter CreateSqlParameter(IDbCommand cmd, string
+parameterName, OracleType dbType) {
+			string marker = parameterName.StartsWith("@") ?
+parameterName.Replace('@', ':') : ":" + parameterName;
+			
+			string sql = cmd.CommandText;
+			int index = sql.IndexOf('?');
+			if (index != -1) {
+				cmd.CommandText = sql.Substring(0, index) + marker +
+sql.Substring(index + 1); 
+			}
+			Console.WriteLine("Parameter: " + marker);
+			return new OracleParameter(marker, dbType);
+		}
+	}
+ }


More information about the mono-bugs mailing list