Przeglądaj źródła

- Transaction Isolation Level is supported
- Fixed TinyInt mapping (Thanks Daniel for finding the bug!)
- ExecuteScalar is supported
- Support CloseConnection CommandBehavior for ExecuteReader
- Implemented full error handling support: OdbcException, OdbcError, OdbcErrorCollection
- Parameter support for all data types (needs further optimization)

svn path=/trunk/mcs/; revision=8429

Brian Ritchie 23 lat temu
rodzic
commit
71d38f2a35

+ 46 - 2
mcs/class/System.Data/System.Data.Odbc/OdbcColumn.cs

@@ -17,14 +17,58 @@ namespace System.Data.Odbc
 		internal OdbcColumn(string Name, OdbcType Type)
 		{
 			this.ColumnName=Name;
-			this.OdbcType=Type;
+			this.OdbcType=Type;		
+			AllowDBNull=false;
+			MaxLength=0;
+			Digits=0;
+			Value=null;
 		}
 
 		internal Type DataType
 		{
 			get
 			{
-				return libodbchelper.ODBCTypeToCILType(OdbcType);
+				switch (OdbcType)
+				{
+					case OdbcType.TinyInt:
+						return typeof(System.Byte);
+					case OdbcType.BigInt: 
+						return typeof(System.Int64);
+					case OdbcType.Image:
+					case OdbcType.VarBinary:
+					case OdbcType.Binary:
+						return typeof(byte[]);
+					case OdbcType.Bit:
+						return typeof(bool);
+					case OdbcType.NChar:
+					case OdbcType.Char:
+						return typeof(char);
+					case OdbcType.Time:
+					case OdbcType.Timestamp:
+					case OdbcType.DateTime:
+					case OdbcType.Date:
+					case OdbcType.SmallDateTime:
+						return typeof(DateTime);
+					case OdbcType.Decimal:
+						return typeof(Decimal);
+					case OdbcType.Numeric:
+					case OdbcType.Double:
+						return typeof(Double);
+					case OdbcType.Int:
+						return typeof(System.Int32);
+					case OdbcType.Text:
+					case OdbcType.NText:
+					case OdbcType.NVarChar:
+					case OdbcType.VarChar:
+						return typeof(string);
+					case OdbcType.Real:
+						return typeof(float);
+					case OdbcType.SmallInt:
+						return typeof(System.Int16);
+					case OdbcType.UniqueIndetifier:
+						return typeof(Guid);
+				}
+				throw new InvalidCastException();
 			}
 		}
 

+ 43 - 24
mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs

@@ -31,8 +31,7 @@ namespace System.Data.Odbc
 		bool designTimeVisible;
 		bool prepared=false;
 		OdbcDataReader dataReader;
-		CommandBehavior behavior;
-		internal IntPtr hstmt;
+		public IntPtr hstmt;
 		
 		#endregion // Fields
 
@@ -48,7 +47,6 @@ namespace System.Data.Odbc
 			transaction = null;
 			designTimeVisible = false;
 			dataReader = null;
-			behavior = CommandBehavior.Default;
 		}
 
 		public OdbcCommand (string cmdText) : this ()
@@ -186,8 +184,9 @@ namespace System.Data.Odbc
 		{
 			if (hstmt!=IntPtr.Zero)
 			{
-				OdbcReturn ret=libodbc.SQLCancel(hstmt);
-				libodbchelper.DisplayError("SQLCancel",ret);
+				OdbcReturn Ret=libodbc.SQLCancel(hstmt);
+				if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLCancel",OdbcHandleType.Stmt,hstmt));
 			}
 			else
 				throw new InvalidOperationException();
@@ -211,25 +210,25 @@ namespace System.Data.Odbc
 		private void ExecSQL(string sql)
 		{
 			OdbcReturn ret;
-	
-			if (!prepared)
-			{
+
+			if ((parameters.Count>0) && !prepared)
 				Prepare();
-				if (Parameters.Count>0)
-					Parameters.Bind(hstmt);
-			}
-			
+	
 			if (prepared)
 			{
 				ret=libodbc.SQLExecute(hstmt);
-				libodbchelper.DisplayError("SQLExecute",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLExecute",OdbcHandleType.Stmt,hstmt));
 			}
 			else
 			{
 				ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
-				libodbchelper.DisplayError("SQLAllocHandle(hstmt)",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
+
 				ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);
-				libodbchelper.DisplayError("SQLExecDirect",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLExecDirect",OdbcHandleType.Stmt,hstmt));
 			}
 		}
 
@@ -245,17 +244,28 @@ namespace System.Data.Odbc
 
 			ExecSQL(CommandText);
 
-			if (!prepared)
-				libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
+//			if (!prepared)
+//				libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
 			return 0;
 		}
 
 		public void Prepare()
 		{
 			OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
-			libodbchelper.DisplayError("SQLAlloc(Prepare)",ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
+
 			ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
-			libodbchelper.DisplayError("SQLPrepare",ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLPrepare",OdbcHandleType.Stmt,hstmt));
+
+			int i=1;
+			foreach (OdbcParameter p in parameters)
+			{
+				p.Bind(hstmt, i);
+				i++;
+			}
+
 			prepared=true;
 		}
 
@@ -272,7 +282,7 @@ namespace System.Data.Odbc
 		public OdbcDataReader ExecuteReader (CommandBehavior behavior)
 		{
 			ExecuteNonQuery();
-			dataReader=new OdbcDataReader(this);
+			dataReader=new OdbcDataReader(this,behavior);
 			return dataReader;
 		}
 
@@ -283,10 +293,19 @@ namespace System.Data.Odbc
 		
 		public object ExecuteScalar ()
 		{
-					throw new NotImplementedException ();
-//			if (connection.DataReader != null)
-//				throw new InvalidOperationException ();
-//			
+			if (connection.DataReader != null)
+				throw new InvalidOperationException ();
+			object val;
+			OdbcDataReader reader=ExecuteReader();
+			try
+			{
+				val=reader[0];
+			}
+			finally
+			{
+				reader.Close();
+			}
+			return val;
 		}
 
 		[MonoTODO]

+ 12 - 7
mcs/class/System.Data/System.Data.Odbc/OdbcConnection.cs

@@ -20,7 +20,7 @@ namespace System.Data.Odbc
 		string connectionString;
 		int connectionTimeout;
 		OdbcDataReader dataReader;
-		internal OdbcTransaction transaction;
+		public OdbcTransaction transaction;
 		IntPtr henv=IntPtr.Zero, hdbc=IntPtr.Zero;
 		
 		#endregion
@@ -33,10 +33,12 @@ namespace System.Data.Odbc
 		
 			// allocate Environment handle	
 			ret=libodbc.SQLAllocHandle(OdbcHandleType.Env, IntPtr.Zero, ref henv);
-			libodbchelper.DisplayError("SQLAllocHandle", ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLAllocHandle"));
 		
 			ret=libodbc.SQLSetEnvAttr(henv, OdbcEnv.OdbcVersion, (IntPtr) 3 , 0); 
-			libodbchelper.DisplayError("SQLSetEnvAttr", ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLSetEnvAttr",OdbcHandleType.Env,henv));
 		
 			//Console.WriteLine("ODBCInit Complete.");
 			connectionTimeout = 15;
@@ -99,7 +101,7 @@ namespace System.Data.Odbc
 			}
 		}
 
-		internal OdbcDataReader DataReader
+		public OdbcDataReader DataReader
 	        {
 			get {
 				return dataReader;
@@ -185,7 +187,8 @@ namespace System.Data.Odbc
 						
 			// allocate connection handle
 			OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Dbc, henv, ref hdbc);
-			libodbchelper.DisplayError("SQLAllocHandle(hdbc)", ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Env,henv));
 			
 			// DSN connection
 			if (connectionString.ToLower().IndexOf("dsn=")>=0)
@@ -209,7 +212,8 @@ namespace System.Data.Odbc
 					}
 				}
 				ret=libodbc.SQLConnect(hdbc, _dsn, -3, _uid, -3, _pwd, -3);
-				libodbchelper.DisplayError("SQLConnect",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLConnect",OdbcHandleType.Dbc,hdbc));
 			}
 			else 
 			{
@@ -218,7 +222,8 @@ namespace System.Data.Odbc
 				short OutLen=0;
 				ret=libodbc.SQLDriverConnect(hdbc, IntPtr.Zero, connectionString, -3, 
 					OutConnectionString, (short) OutConnectionString.Length, ref OutLen, 0);
-				libodbchelper.DisplayError("SQLConnect",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLDriverConnect",OdbcHandleType.Dbc,hdbc));
 			}
 
 		}

+ 25 - 20
mcs/class/System.Data/System.Data.Odbc/OdbcDataReader.cs

@@ -11,7 +11,6 @@ using System.Collections;
 using System.ComponentModel;
 using System.Data;
 using System.Data.Common;
-using System.Runtime.InteropServices;
 
 namespace System.Data.Odbc
 {
@@ -24,14 +23,16 @@ namespace System.Data.Odbc
 		private int currentRow;
 		private OdbcColumn[] cols;
 		private IntPtr hstmt;
+		private CommandBehavior behavior;
 
 		#endregion
 
 		#region Constructors
 
-		internal OdbcDataReader (OdbcCommand command) 
+		internal OdbcDataReader (OdbcCommand command, CommandBehavior behavior) 
 		{
 			this.command = command;
+			this.behavior=behavior;
 			this.command.Connection.DataReader = this;
 			open = true;
 			currentRow = -1;
@@ -118,14 +119,14 @@ namespace System.Data.Odbc
 				byte[] colname_buffer=new byte[bufsize];
 				string colname;
 				short colname_size=0;
-				OdbcType DataType=OdbcType.Int;
 				short ColSize=0, DecDigits=0, Nullable=0, dt=0;
 				OdbcReturn ret=libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal+1), 
 					colname_buffer, bufsize, ref colname_size, ref dt, ref ColSize, 
 					ref DecDigits, ref Nullable);
-				libodbchelper.DisplayError("SQLDescribeCol",ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLDescribeCol",OdbcHandleType.Stmt,hstmt));
 				colname=System.Text.Encoding.Default.GetString(colname_buffer);
-				colname=colname.Replace((char) 0,' ').Trim();
+				colname=colname.Replace((char) 0,' ').Trim();
 				OdbcColumn c=new OdbcColumn(colname, (OdbcType) dt);
 				c.AllowDBNull=(Nullable!=0);
 				c.Digits=DecDigits;
@@ -141,12 +142,16 @@ namespace System.Data.Odbc
 			// libodbc.SQLFreeHandle((ushort) OdbcHandleType.Stmt, hstmt);
 		
 			OdbcReturn ret=libodbc.SQLCloseCursor(hstmt);
-			libodbchelper.DisplayError("SQLCancel",ret);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLCloseCursor",OdbcHandleType.Stmt,hstmt));
 	
 			open = false;
 			currentRow = -1;
 
 			this.command.Connection.DataReader = null;
+
+			if ((behavior & CommandBehavior.CloseConnection)==CommandBehavior.CloseConnection)
+				this.command.Connection.Close();
 		}
 
 		~OdbcDataReader ()
@@ -263,14 +268,14 @@ namespace System.Data.Odbc
 		}
 
 		[MonoTODO]
-		public DataTable GetSchemaTable() 
+		public DataTable GetSchemaTable() 
 		{	
 
 			DataTable dataTableSchema = null;
 			// Only Results from SQL SELECT Queries 
 			// get a DataTable for schema of the result
 			// otherwise, DataTable is null reference
-			if(cols.Length > 0) 
+			if(cols.Length > 0) 
 			{
 				
 				dataTableSchema = new DataTable ();
@@ -299,10 +304,10 @@ namespace System.Data.Odbc
 				dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
 				dataTableSchema.Columns.Add ("IsLong", typeof (bool));
 				dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
-
+
 				DataRow schemaRow;
 								
-				for (int i = 0; i < cols.Length; i += 1 ) 
+				for (int i = 0; i < cols.Length; i += 1 ) 
 				{
 					OdbcColumn col=GetColumn(i);
 					//Console.WriteLine("{0}:{1}:{2}",col.ColumnName,col.DataType,col.OdbcType);
@@ -318,13 +323,13 @@ namespace System.Data.Odbc
 					schemaRow["NumericScale"] = 0;
 					// TODO: need to get KeyInfo
 					schemaRow["IsUnique"] = false;
-					schemaRow["IsKey"] = DBNull.Value;					
+					schemaRow["IsKey"] = DBNull.Value;					
 
 					schemaRow["BaseCatalogName"] = "";				
 					schemaRow["BaseColumnName"] = col.ColumnName;
 					schemaRow["BaseSchemaName"] = "";
 					schemaRow["BaseTableName"] = "";
-					schemaRow["DataType"] = col.DataType;
+					schemaRow["DataType"] = col.DataType;
 
 					schemaRow["AllowDBNull"] = col.AllowDBNull;
 					
@@ -339,12 +344,12 @@ namespace System.Data.Odbc
 					schemaRow["IsLong"] = false;
 					schemaRow["IsReadOnly"] = false;
 					
-					schemaRow.AcceptChanges();
+	//				schemaRow.AcceptChanges();
 					
 				}
 
 			}
-			
+			dataTableSchema.AcceptChanges();
 			return dataTableSchema;
 		}
 
@@ -404,8 +409,8 @@ namespace System.Data.Odbc
 						ret=libodbc.SQLGetData(hstmt, ColIndex, OdbcType.BigInt, ref long_data, 0, ref outsize);
 						DataValue=long_data;
 						break;
-					case OdbcType.NVarChar:
-						bufsize=col.MaxLength*2+1; // Unicode is double byte
+					case OdbcType.NVarChar:
+						bufsize=col.MaxLength*2+1; // Unicode is double byte
 						buffer=new byte[bufsize];
 						ret=libodbc.SQLGetData(hstmt, ColIndex, OdbcType.NVarChar, buffer, bufsize, ref outsize);
 						if (outsize!=-1)
@@ -440,13 +445,13 @@ namespace System.Data.Odbc
 						break;
 				}
 
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLGetData",OdbcHandleType.Stmt,hstmt));
+
 				if (outsize==-1) // This means SQL_NULL_DATA 
 					col.Value=DBNull.Value;
 				else
-				{
-					libodbchelper.DisplayError("SQLGetData("+col.OdbcType.ToString()+")",ret);
-					col.Value=DataValue;	
-				}
+					col.Value=DataValue;
 			}
 			return col.Value;
 		}

+ 45 - 17
mcs/class/System.Data/System.Data.Odbc/OdbcParameter.cs

@@ -18,7 +18,7 @@ namespace System.Data.Odbc
 		#region Fields
 
 		string name;
-		object value;
+		object ParamValue;
 		int size;
 		bool isNullable;
 		byte precision;
@@ -29,7 +29,10 @@ namespace System.Data.Odbc
 		OdbcType odbcType;
 		DbType dbType;
 
-		int IntValue;
+		// Buffers for parameter value based on type. Currently I've only optimized 
+		// for int parameters and everything else is just converted to a string.
+		int intbuf;
+		byte[] buffer;
 
 		#endregion
 
@@ -38,7 +41,7 @@ namespace System.Data.Odbc
 		public OdbcParameter ()
 		{
 			name = String.Empty;
-			value = null;
+			ParamValue = null;
 			size = 0;
 			isNullable = true;
 			precision = 0;
@@ -50,7 +53,7 @@ namespace System.Data.Odbc
 			: this ()
 		{
 			this.name = name;
-			this.value = value;
+			this.ParamValue = value;
 		}
 
 		public OdbcParameter (string name, OdbcType dataType) 
@@ -58,11 +61,6 @@ namespace System.Data.Odbc
 		{
 			this.name = name;
 			OdbcType = dataType;
-
-			// These paramter types aren't supported yet...
-			if (odbcType==OdbcType.Date || odbcType==OdbcType.Time || odbcType==OdbcType.DateTime ||
-				OdbcType==OdbcType.Timestamp || odbcType==OdbcType.SmallDateTime)
-				throw new NotSupportedException();
 		}
 
 		public OdbcParameter (string name, OdbcType dataType, int size)
@@ -85,7 +83,7 @@ namespace System.Data.Odbc
 			this.precision = precision;
 			this.scale = scale;
 			this.sourceVersion = srcVersion;
-			this.value = value;
+			this.ParamValue = value;
 		}
 
 		#endregion
@@ -147,22 +145,52 @@ namespace System.Data.Odbc
 		
 		public object Value {
 			get { 
-				return IntValue;
+				return ParamValue;
+			}
+			set { 
+				this.ParamValue = value; 
+				// Load buffer with new value
+				if (odbcType==OdbcType.Int)
+					intbuf=(int) value;
+				else
+				{
+					// Treat everything else as a string
+					// Init string buffer
+					if (buffer==null || buffer.Length< ((size>20)?size:20) )
+						buffer=new byte[(size>20)?size:20];
+					else
+						buffer.Initialize();
+					// Convert value into string and store into buffer
+					byte[] strValueBuffer=System.Text.Encoding.ASCII.GetBytes(ParamValue.ToString());
+					strValueBuffer.CopyTo(buffer,0);
+				}
 			}
-			set { this.IntValue =(int) value; }
 		}
 
 		#endregion // Properties
 
-		#region Internal Properties
+		#region public Properties
 
-		internal void Bind(IntPtr hstmt,int ParamNum)
+		public void Bind(IntPtr hstmt,int ParamNum)
 		{
-			OdbcReturn ret=libodbc.SQLBindParam(hstmt, Convert.ToInt16(ParamNum), (short) odbcType, (short) odbcType, 0,0,ref IntValue, 0);
-			libodbchelper.DisplayError("SQLBindParam",ret);		
+			OdbcReturn ret;
+			// Convert System.Data.ParameterDirection into odbc enum
+			OdbcInputOutputDirection paramdir=libodbc.ConvertParameterDirection(this.direction);
+			// Bind parameter based on type
+			if (odbcType==OdbcType.Int)
+				ret=libodbc.SQLBindParameter(hstmt, (ushort) ParamNum, (short) paramdir, 
+					(short) odbcType, (short) odbcType, Convert.ToUInt32(size), 
+					0, ref intbuf, 0, 0);
+			else
+				ret=libodbc.SQLBindParameter(hstmt, (ushort) ParamNum, 	(short) paramdir,
+					(short) OdbcType.Char, (short) odbcType, Convert.ToUInt32(size), 
+					0, 	buffer, 0, 0);
+			// Check for error condition
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLBindParam",OdbcHandleType.Stmt,hstmt));
 		}
 		
-		#endregion // Internal Properties
+		#endregion // public Properties
 
 		#region Methods
 

+ 1 - 2
mcs/class/System.Data/System.Data.Odbc/OdbcParameterCollection.cs

@@ -1,4 +1,3 @@
-
 //
 // System.Data.Odbc.OdbcParameterCollection
 //
@@ -119,7 +118,7 @@ namespace System.Data.Odbc
 		}
 
 
-		internal void Bind(IntPtr hstmt)
+		public void Bind(IntPtr hstmt)
 		{
 			for (int i=0;i<Count;i++)
 			{

+ 32 - 5
mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs

@@ -22,9 +22,34 @@ namespace System.Data.Odbc
 		internal OdbcTransaction(OdbcConnection conn, IsolationLevel isolationlevel)
 		{
 			// Set Auto-commit (102) to false
-			OdbcReturn ret=libodbc.SQLSetConnectAttr(conn.hDbc, 102, 0, 0); 
-			libodbchelper.DisplayError("SQLSetConnectAttr(NoAutoCommit)", ret);
-			// TODO: Handle isolation level
+			OdbcReturn ret=libodbc.SQLSetConnectAttr(conn.hDbc, OdbcConnectionAttribute.AutoCommit, IntPtr.Zero, 0); 
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLSetConnectAttr",OdbcHandleType.Dbc,conn.hDbc));
+			// Handle isolation level
+			int lev=0;
+			switch (isolationlevel)
+			{
+				case IsolationLevel.ReadUncommitted:
+					lev=1;
+					break;				
+				case IsolationLevel.ReadCommitted:
+					lev=2;
+					break;
+				case IsolationLevel.RepeatableRead:
+					lev=3;
+					break;
+				case IsolationLevel.Serializable:
+					lev=4;
+					break;
+				case IsolationLevel.Unspecified:
+					lev=0;
+					break;
+				default:
+					throw new NotSupportedException();
+			}
+			libodbc.SQLSetConnectAttr(conn.hDbc, OdbcConnectionAttribute.TransactionIsolation, (IntPtr) lev, 0);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLSetConnectAttr",OdbcHandleType.Dbc,conn.hDbc));
 			this.isolationlevel=isolationlevel;
 			connection=conn;
 		}
@@ -34,7 +59,8 @@ namespace System.Data.Odbc
 			if (connection.transaction==this)
 			{
 				OdbcReturn ret=libodbc.SQLEndTran((short) OdbcHandleType.Dbc, connection.hDbc, 0);
-				libodbchelper.DisplayError("SQLEndTran(commit)", ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLEndTran",OdbcHandleType.Dbc,connection.hDbc));
 				connection.transaction=null;
 			}
 			else
@@ -46,7 +72,8 @@ namespace System.Data.Odbc
 			if (connection.transaction==this)
 			{
 				OdbcReturn ret=libodbc.SQLEndTran((short) OdbcHandleType.Dbc, connection.hDbc, 1);
-				libodbchelper.DisplayError("SQLEndTran(rollback)", ret);
+				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+					throw new OdbcException(new OdbcError("SQLEndTran",OdbcHandleType.Dbc,connection.hDbc));
 				connection.transaction=null;
 			}
 			else

+ 89 - 37
mcs/class/System.Data/System.Data.Odbc/libodbc.cs

@@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
 
 namespace System.Data.Odbc
 {
-	internal enum OdbcHandleType : ushort {
+	internal enum OdbcHandleType : short {
 		Env = 1,
 		Dbc = 2,
 		Stmt = 3,
@@ -38,103 +38,155 @@ namespace System.Data.Odbc
 		CPMatch = 202
 	}
 
+	internal enum OdbcConnectionAttribute : int 
+	{
+		AutoCommit=102,
+		TransactionIsolation=108
+	}
+
+	internal enum OdbcInputOutputDirection : short
+	{
+		Input=1,
+		InputOutput=2,
+		ResultCol=3,
+		Output=4,
+		ReturnValue=5
+	}
+
 	[StructLayout(LayoutKind.Sequential)]
 	internal struct OdbcTimestamp
 	{
-		public short year;
-		public ushort month;
-		public ushort day;
-		public ushort hour;
-		public ushort minute;
-		public ushort second;
-		public ulong fraction;
+		internal short year;
+		internal ushort month;
+		internal ushort day;
+		internal ushort hour;
+		internal ushort minute;
+		internal ushort second;
+		internal ulong fraction;
 	}
 
 	
 //	sealed internal class libodbc
 	internal class libodbc
 	{
+		internal static OdbcInputOutputDirection ConvertParameterDirection(
+			ParameterDirection dir)
+		{
+			switch (dir)
+			{
+				case ParameterDirection.Input:
+					return OdbcInputOutputDirection.Input;
+				case ParameterDirection.InputOutput:
+					return OdbcInputOutputDirection.InputOutput;
+				case ParameterDirection.Output:
+					return OdbcInputOutputDirection.Output;
+				case ParameterDirection.ReturnValue:
+					return OdbcInputOutputDirection.ReturnValue;
+				default:
+					return OdbcInputOutputDirection.Input;
+			}
+		}
+
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLAllocHandle (OdbcHandleType HandleType, IntPtr InputHandle, ref IntPtr OutputHandlePtr);
+		internal static extern OdbcReturn SQLAllocHandle (OdbcHandleType HandleType, IntPtr InputHandle, ref IntPtr OutputHandlePtr);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLSetEnvAttr (IntPtr EnvHandle, OdbcEnv Attribute, IntPtr Value, int StringLength);
+		internal static extern OdbcReturn SQLSetEnvAttr (IntPtr EnvHandle, OdbcEnv Attribute, IntPtr Value, int StringLength);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLConnect (IntPtr ConnectionHandle, string ServerName, short NameLength1, string UserName, short NameLength2, string Authentication, short NameLength3);
+		internal static extern OdbcReturn SQLConnect (IntPtr ConnectionHandle, string ServerName, short NameLength1, string UserName, short NameLength2, string Authentication, short NameLength3);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn  SQLDriverConnect(IntPtr ConnectionHandle, IntPtr WindowHandle, string InConnectionString, short StringLength1, string OutConnectionString, short BufferLength,	ref short StringLength2Ptr,	ushort DriverCompletion);
+		internal static extern OdbcReturn  SQLDriverConnect(IntPtr ConnectionHandle, IntPtr WindowHandle, string InConnectionString, short StringLength1, string OutConnectionString, short BufferLength,	ref short StringLength2Ptr,	ushort DriverCompletion);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLExecDirect (IntPtr StatementHandle, string StatementText, int TextLength);
+		internal static extern OdbcReturn SQLExecDirect (IntPtr StatementHandle, string StatementText, int TextLength);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLRowCount (IntPtr StatementHandle, ref int RowCount);
+		internal static extern OdbcReturn SQLRowCount (IntPtr StatementHandle, ref int RowCount);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLNumResultCols (IntPtr StatementHandle, ref short ColumnCount);
+		internal static extern OdbcReturn SQLNumResultCols (IntPtr StatementHandle, ref short ColumnCount);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLFetch (IntPtr StatementHandle);
+		internal static extern OdbcReturn SQLFetch (IntPtr StatementHandle);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref bool TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref bool TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref double TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref double TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref long TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref long TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref short TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref short TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref float TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref float TargetPtr, int BufferLen, ref int Len);
 	
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref OdbcTimestamp TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref OdbcTimestamp TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref int TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, ref int TargetPtr, int BufferLen, ref int Len);
 	
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, byte[] TargetPtr, int BufferLen, ref int Len);
+		internal static extern OdbcReturn SQLGetData (IntPtr StatementHandle, ushort ColumnNumber, OdbcType TargetType, byte[] TargetPtr, int BufferLen, ref int Len);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLDescribeCol(IntPtr StatementHandle, ushort ColumnNumber, byte[] ColumnName, short BufferLength, ref short NameLength, ref short DataType, ref short ColumnSize, ref short DecimalDigits, ref short Nullable);
+		internal static extern OdbcReturn SQLDescribeCol(IntPtr StatementHandle, ushort ColumnNumber, byte[] ColumnName, short BufferLength, ref short NameLength, ref short DataType, ref short ColumnSize, ref short DecimalDigits, ref short Nullable);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLFreeHandle(ushort HandleType, IntPtr SqlHandle);
+		internal static extern OdbcReturn SQLFreeHandle(ushort HandleType, IntPtr SqlHandle);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLDisconnect(IntPtr ConnectionHandle);
+		internal static extern OdbcReturn SQLDisconnect(IntPtr ConnectionHandle);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLPrepare(IntPtr StatementHandle, string Statement, int TextLength);
+		internal static extern OdbcReturn SQLPrepare(IntPtr StatementHandle, string Statement, int TextLength);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLExecute(IntPtr StatementHandle);
+		internal static extern OdbcReturn SQLExecute(IntPtr StatementHandle);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLSetConnectAttr(IntPtr ConnectionHandle, int Attribute, uint Value, int Length);
+		internal static extern OdbcReturn SQLSetConnectAttr(IntPtr ConnectionHandle, OdbcConnectionAttribute Attribute, IntPtr Value, int Length);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLEndTran(int HandleType, IntPtr Handle, short CompletionType);
+		internal static extern OdbcReturn SQLEndTran(int HandleType, IntPtr Handle, short CompletionType);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLBindParam(IntPtr StatementHandle, short ParamNum, short ValueType,
-				short ParamType, int LenPrecision, short ParamScale, ref int ParamValue, int StrLen);
+		internal static extern OdbcReturn SQLBindParameter(IntPtr StatementHandle, ushort ParamNum, 
+				short InputOutputType, short ValueType, short ParamType, uint ColSize, 
+				short DecimalDigits, byte[] ParamValue, int BufLen, int StrLen);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLBindParam(IntPtr StatementHandle, short ParamNum, short ValueType,
-				short ParamType, int LenPrecision, short ParamScale, byte[] ParamValue, int StrLen);
+		internal static extern OdbcReturn SQLBindParameter(IntPtr StatementHandle, ushort ParamNum, 
+				short InputOutputType, short ValueType, short ParamType, uint ColSize, 
+				short DecimalDigits, ref int ParamValue, int BufLen, int StrLen);
 
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLCancel(IntPtr StatementHandle);
+		internal static extern OdbcReturn SQLCancel(IntPtr StatementHandle);
 		
 		[DllImport("odbc32.dll")]
-		public static extern OdbcReturn SQLCloseCursor(IntPtr StatementHandle);
+		internal static extern OdbcReturn SQLCloseCursor(IntPtr StatementHandle);
+
+		[DllImport("odbc32.dll")]
+		internal static extern OdbcReturn SQLError(IntPtr EnvironmentHandle,
+							   IntPtr ConnectionHandle, IntPtr StatementHandle,
+							   byte[] Sqlstate, ref int NativeError,
+							   byte[] MessageText, short BufferLength,
+							   ref short TextLength);
+
+		[DllImport("odbc32.dll")]
+		internal static extern OdbcReturn SQLGetStmtAttr(IntPtr StatementHandle,
+								int Attribute, ref IntPtr Value, int BufLen, int StrLen);
+
+		[DllImport("odbc32.dll")]
+		internal static extern OdbcReturn SQLSetDescField(IntPtr DescriptorHandle,
+			short RecNumber, short FieldIdentifier, byte[] Value, int BufLen);
+		
+
 	}
 }

+ 0 - 63
mcs/class/System.Data/System.Data.Odbc/libodbchelper.cs

@@ -1,63 +0,0 @@
-using System;
-
-namespace System.Data.Odbc
-{
-	/// <summary>
-	/// Summary description for libodbchelper.
-	/// </summary>
-	internal class libodbchelper
-	{
-		public static void DisplayError(string Msg, OdbcReturn Ret)
-		{
-			if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo)) 
-			{
-				Console.WriteLine("ERROR: {0}: <{1}>",Msg,Ret);
-		
-			}
-		}
-
-		internal static Type ODBCTypeToCILType(OdbcType type)
-		{
-			switch (type)
-			{
-				case OdbcType.BigInt: 
-					return typeof(System.Int64);
-				case OdbcType.Image:
-				case OdbcType.VarBinary:
-				case OdbcType.Binary:
-					return typeof(byte[]);
-				case OdbcType.Bit:
-					return typeof(bool);
-				case OdbcType.NChar:
-				case OdbcType.Char:
-					return typeof(char);
-				case OdbcType.Time:
-				case OdbcType.Timestamp:
-				case OdbcType.DateTime:
-				case OdbcType.Date:
-				case OdbcType.SmallDateTime:
-					return typeof(DateTime);
-				case OdbcType.Decimal:
-					return typeof(Decimal);
-				case OdbcType.Numeric:
-				case OdbcType.Double:
-					return typeof(Double);
-				case OdbcType.Int:
-					return typeof(System.Int32);
-				case OdbcType.Text:
-				case OdbcType.NText:
-				case OdbcType.NVarChar:
-				case OdbcType.VarChar:
-					return typeof(string);
-				case OdbcType.Real:
-					return typeof(float);
-				case OdbcType.SmallInt:
-					return typeof(System.Int16);
-				case OdbcType.UniqueIndetifier:
-					return typeof(Guid);
-			}
-			throw new InvalidCastException();
-		}
-
-	}
-}