[Mono-list] ODBC.NET Data Provider
Brian Ritchie
brianlritchie@hotmail.com
Wed, 09 Oct 2002 09:48:29 -0400
This is a multi-part message in MIME format.
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; format=flowed
Ok...I've attached the ODBC.NET files. Could someone put them in CVS for
me? Thanks :)
Just a couple of notes:
- The code is still in the works...but I've performed selects and inserts
with it (including parameterized queries).
- Requires unixODBC to be installed and configured
- I've tested it on Debian with DB2
Known Issues:
- Only works with DSN connections (no DSN-less yet)
- It has transaction support, but not through the Transaction object
- Parameters only support integer types
- DBNull is not handled correctly
- Currently most errors are printed to the console instead of throwing
exceptions...this wil change as I tighten things up.
Any feedback is appreciated...
Brian
>From: "Daniel Morgan" <danmorg@sc.rr.com>
>To: "Brian Ritchie" <brianlritchie@hotmail.com>, <mono-list@ximian.com>
>Subject: RE: [Mono-list] ODBC.NET Data Provider
>Date: Wed, 9 Oct 2002 01:40:07 -0400
>
>Hey Brian,
>
>Once you contribute something, you can get a cvs account. You can attach
>your patch or files in an email to this list. Someone like Rodrigo, me, or
>someone else would be happy to commit it for you. Rodrigo is real good at
>this because he does a code review and let's you know what improvements can
>be done to it.
>
>Once something of yours has been contributed, you need to go
>to http://www.go-mono.com/ccvs.html
>and follow those directions on getting your own cvs account.
>
>Happy hacking,
>Daniel
>
>-----Original Message-----
>From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com]On
>Behalf Of Brian Ritchie
>Sent: Wednesday, October 09, 2002 12:34 AM
>To: danmorg@sc.rr.com; mono-list@ximian.com
>Subject: RE: [Mono-list] ODBC.NET Data Provider
>
>
>Daniel,
>
>Do I need to get setup with CVS access first?
>
>Brian
>
>
> >From: "Daniel Morgan" <danmorg@sc.rr.com>
> >To: "Brian Ritchie" <brianlritchie@hotmail.com>, <mono-list@ximian.com>
> >Subject: RE: [Mono-list] ODBC.NET Data Provider
> >Date: Tue, 8 Oct 2002 23:11:06 -0400
> >
> >Brian,
> >
> >Being able to connet to a database and do queries is a milestone in
>itself.
> >It wouldn't hurt to go ahead and check it into cvs. Besides, I feel
>safer
> >anything I have worked on has been put into cvs because I know Ximian
>guys
> >keep things backed up unlike my computer. :-)
> >
> >I don't know what the namespace or assembly for the ODBC provider in .NET
> >1.1, but the MSDN download of the ODBC provider for .NET 1.0 uses
> >Microsoft.Data.Odbc as the namespace and Microsoft.Data.Odbc.dll as the
> >assembly name.
> >
> >We have SQL# which is a command-line SQL query tool written in C# that
>can
> >connect to various databases using the various ADO.NET providers. It can
> >be
> >found
> >at mcs/class/System.Data/Test/SqlSharpCli.cs However, don't be to
> >disappointed in the tool, it was mainly meant for testing Mono's
> >System.Data.
> >
> >What would be nice is to have a MS SQL Server 2000 Enterprise Manager,
> >Query
> >Analyzer, or TOAD like tool for Mono System.Data written in C# and using
> >GTK#.
> >
> >Daniel
> >
> >-----Original Message-----
> >From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com]On
> >Behalf Of Brian Ritchie
> >Sent: Tuesday, October 08, 2002 9:39 PM
> >To: danmorg@sc.rr.com; mono-list@ximian.com
> >Subject: RE: [Mono-list] ODBC.NET Data Provider
> >
> >
> >Sounds good, I've got a little more work before I send in the patch. I
> >don't want to send in anything that is too raw :)
> >
> >Has anyone looked at .NET 1.1 yet? I'm assuming they are moving the Odbc
> >stuff under the System.Data namespace...so that is how my stuff is setup.
> >(System.Data.Odbc)
> >
> >Have you guys talked about providing any basic db tools with the mono
> >framework? Like a isql-style command line tool? This might be a good
>way
> >for people to test their database connections, etc.
> >
> >Keep up the good work guys...the framework is looking good.
> >
> >Brian
> >
> >
> > >From: "Daniel Morgan" <danmorg@sc.rr.com>
> > >To: "Brian Ritchie" <brianlritchie@hotmail.com>, <mono-list@ximian.com>
> > >Subject: RE: [Mono-list] ODBC.NET Data Provider
> > >Date: Mon, 7 Oct 2002 01:08:32 -0400
> > >
> > >Brian,
> > >
> > >This is good news.
> > >
> > >Can provide us with a patch please in an email to the
> >mono-list@ximian.com?
> > >If you don't know how to make a patch, you can look here on how:
> > >http://www.go-mono.com/ccvs.html
> > >
> > >This way people can get a preview of your work and be able to help
> > >contribute too. Since unixODBC supports so many databases, it will
> > >definitely be appreciated.
> > >
> > >Do you know if unixODBC works on Windows?
> > >
> > >Thanks,
> > >Daniel
> > >
> > >-----Original Message-----
> > >From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com]On
> > >Behalf Of Brian Ritchie
> > >Sent: Monday, October 07, 2002 12:02 AM
> > >To: danmorg@sc.rr.com; mono-list@ximian.com
> > >Subject: RE: [Mono-list] ODBC.NET Data Provider
> > >
> > >
> > >Daniel,
> > >
> > >Thanks for the quick response. I have basic implementations of
> > >OdbcConnection, OdbcCommand, OdbcDataReader, OdbcParameter, and
> > >OdbcParameterCollection. It can execute queries and display result
>sets
> > >(and ExecuteNonQuery too). I'm currently working on the Parameter &
> > >Transaction support. I've been doing my development on Debian against
>a
> > >DB2
> > >7.2 UDB.
> > >
> > >Brian
> > >
> > >
> > > >From: "Daniel Morgan" <danmorg@sc.rr.com>
> > > >To: "Brian Ritchie" <brianlritchie@hotmail.com>,
><mono-list@ximian.com>
> > > >Subject: RE: [Mono-list] ODBC.NET Data Provider
> > > >Date: Sun, 6 Oct 2002 22:51:07 -0400
> > > >
> > > >Brian
> > > >
> > > >No one is working on the ODBC.NET Data Provider as far as i know.
>Just
> > > >attach your diff in an email, and someone, such as (passing the buck
>-
> > > >hehehe) Rodrigo Moya can do that for you. Rodrigo is the coordinator
> >for
> > > >the
> > > >ADO.NET technology in Mono.
> > > >
> > > >What can you do witht he provider so far? Can you connect to a
> >database
> > > >yet? How about run any queries? Or is it just C# bindings to the
> > >unixODBC
> > > >library(ies) right now?
> > > >
> > > >Daniel
> > > >
> > > >-----Original Message-----
> > > >From: mono-list-admin@ximian.com
>[mailto:mono-list-admin@ximian.com]On
> > > >Behalf Of Brian Ritchie
> > > >Sent: Sunday, October 06, 2002 10:03 PM
> > > >To: mono-list@ximian.com
> > > >Subject: [Mono-list] ODBC.NET Data Provider
> > > >
> > > >
> > > >Is anyone working on a ODBC data provider? I've started one using
> > >unixodbc
> > > >and I'd like to contribute it to the project.
> > > >
> > > >Brian
>
>
>
>
>_________________________________________________________________
>Send and receive Hotmail on your mobile device: http://mobile.msn.com
>
>
>_______________________________________________
>Mono-list maillist - Mono-list@ximian.com
>http://lists.ximian.com/mailman/listinfo/mono-list
>
>
>_______________________________________________
>Mono-list maillist - Mono-list@ximian.com
>http://lists.ximian.com/mailman/listinfo/mono-list
_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="libodbc.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="libodbc.cs"
//
// System.Data.Odbc.libodbc
//
// Authors:
// Brian Ritchie (brianlritchie@hotmail.com)
//
//
// Copyright (C) Brian Ritchie, 2002
//
//
using System.Data;
using System.Data.Common;
using System.Runtime.InteropServices;
namespace System.Data.Odbc
{
internal enum OdbcHandleType {
Env = 1,
Dbc = 2,
Stmt = 3,
Desc = 4
};
internal enum OdbcReturn {
Error = -1,
InvalidHandle = -2,
StillExecuting = 2,
NeedData = 99,
Success = 0,
SuccessWithInfo = 1
}
internal enum OdbcEnv {
OdbcVersion = 200,
ConnectionPooling = 201,
CPMatch = 202
}
[StructLayout(LayoutKind.Sequential)]
public struct OdbcTimestamp
{
public short year;
public ushort month;
public ushort day;
public ushort hour;
public ushort minute;
public ushort second;
public ulong fraction;
}
sealed internal class libodbc
{
public static void DisplayError(string Msg, OdbcReturn Ret)
{
if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo)) {
Console.WriteLine("ERROR: {0}: <{1}>",Msg,Ret);
}
}
[DllImport("libodbc")]
public static extern OdbcReturn SQLAllocHandle (ushort HandleType, int
InputHandle, ref int OutputHandlePtr);
[DllImport("libodbc")]
public static extern OdbcReturn SQLSetEnvAttr (int EnvHandle, ushort
Attribute, IntPtr Value, int StringLength);
[DllImport("libodbc")]
public static extern OdbcReturn SQLConnect (int ConnectionHandle, string
ServerName, short NameLength1, string UserName, short NameLength2, string
Authentication, short NameLength3);
[DllImport("libodbc")]
public static extern OdbcReturn SQLExecDirect (int StatementHandle, string
StatementText, int TextLength);
[DllImport("libodbc")]
public static extern OdbcReturn SQLRowCount (int StatementHandle, ref int
RowCount);
[DllImport("libodbc")]
public static extern OdbcReturn SQLNumResultCols (int StatementHandle, ref
short ColumnCount);
[DllImport("libodbc")]
public static extern OdbcReturn SQLFetch (int StatementHandle);
[DllImport("libodbc")]
public static extern OdbcReturn SQLGetData (int StatementHandle, ushort
ColumnNumber, short TargetType, ref int TargetPtr, int BufferLen, ref int
Len);
[DllImport("libodbc")]
public static extern OdbcReturn SQLGetData (int StatementHandle, ushort
ColumnNumber, short TargetType, byte[] TargetPtr, int BufferLen, ref int
Len);
[DllImport("libodbc")]
public static extern OdbcReturn SQLGetData (int StatementHandle, ushort
ColumnNumber, short TargetType, ref float TargetPtr, int BufferLen, ref int
Len);
[DllImport("libodbc")]
public static extern OdbcReturn SQLGetData (int StatementHandle, ushort
ColumnNumber, short TargetType, ref OdbcTimestamp TargetPtr, int BufferLen,
ref int Len);
[DllImport("libodbc")]
public static extern OdbcReturn SQLDescribeCol(int StatmentHandle, ushort
ColumnNumber, byte[] ColumnName, short BufferLength, ref short NameLength,
ref short DataType, ref short ColumnSize, ref short DecimalDigits, ref short
Nullable);
[DllImport("libodbc")]
public static extern OdbcReturn SQLFreeHandle(ushort HandleType, int
SqlHandle);
[DllImport("libodbc")]
public static extern OdbcReturn SQLDisconnect(int ConnectionHandle);
[DllImport("libodbc")]
public static extern OdbcReturn SQLPrepare(int StatementHandle, string
Statement, int TextLength);
[DllImport("libodbc")]
public static extern OdbcReturn SQLExecute(int StatementHandle);
[DllImport("libodbc")]
public static extern OdbcReturn SQLSetConnectAttr(int ConnectionHandle,
int Attribute, uint Value, int Length);
[DllImport("libodbc")]
public static extern OdbcReturn SQLEndTran(int HandleType, int Handle,
short CompletionType);
[DllImport("libodbc")]
public static extern OdbcReturn SQLBindParam(int StatementHandle, short
ParamNum, short ValueType,
short ParamType, int LenPrecision, short ParamScale, ref int ParamValue,
int StrLen);
[DllImport("libodbc")]
public static extern OdbcReturn SQLBindParam(int StatementHandle, short
ParamNum, short ValueType,
short ParamType, int LenPrecision, short ParamScale, byte[] ParamValue,
int StrLen);
[DllImport("libodbc")]
public static extern OdbcReturn SQLCancel(int StatementHandle);
[DllImport("libodbc")]
public static extern OdbcReturn SQLCloseCursor(int StatementHandle);
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcCommand.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcCommand.cs"
//
// System.Data.Odbc.OdbcCommand
//
// Authors:
// Brian Ritchie (brianlritchie@hotmail.com)
//
// Copyright (C) Brian Ritchie, 2002
//
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Collections;
using System.Runtime.InteropServices;
namespace System.Data.Odbc
{
/// <summary>
/// Represents an SQL statement or stored procedure to execute against a
data source.
/// </summary>
public sealed class OdbcCommand : Component, ICloneable, IDbCommand
{
#region Fields
string commandText;
int timeout;
CommandType commandType;
OdbcConnection connection;
OdbcParameterCollection parameters;
//OdbcTransaction transaction;
bool designTimeVisible;
bool prepared=false;
OdbcDataReader dataReader;
CommandBehavior behavior;
public int hstmt;
#endregion // Fields
#region Constructors
public OdbcCommand ()
{
commandText = String.Empty;
timeout = 30; // default timeout
commandType = CommandType.Text;
connection = null;
parameters = new OdbcParameterCollection ();
//transaction = null;
designTimeVisible = false;
dataReader = null;
behavior = CommandBehavior.Default;
}
public OdbcCommand (string cmdText) : this ()
{
CommandText = cmdText;
}
public OdbcCommand (string cmdText, OdbcConnection connection)
: this (cmdText)
{
Connection = connection;
}
// public OdbcCommand (string cmdText,
// OdbcConnection connection,
// OdbcTransaction transaction) : this (cmdText, connection)
// {
// this.transaction = transaction;
// }
#endregion // Constructors
#region Properties
public int hStmt
{
get { return hstmt; }
}
public string CommandText
{
get {
return commandText;
}
set {
prepared=false;
commandText = value;
}
}
public int CommandTimeout {
get {
return timeout;
}
set {
timeout = value;
}
}
public CommandType CommandType {
get {
return commandType;
}
set {
commandType = value;
}
}
public OdbcConnection Connection {
get {
return connection;
}
set {
connection = value;
}
}
public bool DesignTimeVisible {
get {
return designTimeVisible;
}
set {
designTimeVisible = value;
}
}
public OdbcParameterCollection Parameters {
get {
return parameters;
}
set {
parameters = value;
}
}
// public OdbcTransaction Transaction {
// get {
// return transaction;
// }
// set {
// transaction = value;
// }
// }
public UpdateRowSource UpdatedRowSource {
[MonoTODO]
get {
throw new NotImplementedException ();
}
[MonoTODO]
set {
throw new NotImplementedException ();
}
}
IDbConnection IDbCommand.Connection {
get {
return Connection;
}
set {
Connection = (OdbcConnection) value;
}
}
IDataParameterCollection IDbCommand.Parameters {
get {
throw new NotImplementedException ();
//return Parameters;
}
}
IDbTransaction IDbCommand.Transaction {
get {
throw new NotImplementedException ();
//return Transaction;
}
set {
throw new NotImplementedException ();
}
}
#endregion // Properties
#region Methods
[MonoTODO]
public void Cancel ()
{
throw new NotImplementedException ();
}
public OdbcParameter CreateParameter ()
{
return new OdbcParameter ();
}
IDbDataParameter IDbCommand.CreateParameter ()
{
return CreateParameter ();
}
[MonoTODO]
protected override void Dispose (bool disposing)
{
throw new NotImplementedException ();
}
protected void ExecSQL(string sql)
{
OdbcReturn ret;
if (!prepared)
{
Prepare();
if (Parameters.Count>0)
Parameters.Bind(hstmt);
}
if (prepared)
{
ret=libodbc.SQLExecute(hstmt);
libodbc.DisplayError("SQLExecute",ret);
}
else
{
ret=libodbc.SQLAllocHandle((ushort) OdbcHandleType.Stmt,
Connection.hDbc, ref hstmt);
libodbc.DisplayError("SQLAllocHandle(hstmt)",ret);
ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);
libodbc.DisplayError("SQLExecDirect",ret);
}
}
public int ExecuteNonQuery ()
{
if (connection == null)
throw new InvalidOperationException ();
if (connection.State == ConnectionState.Closed)
throw new InvalidOperationException ();
// FIXME: a third check is mentioned in .NET docs
if (connection.DataReader != null)
throw new InvalidOperationException ();
ExecSQL(CommandText);
if (!prepared)
libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
return 0;
}
public void Prepare()
{
OdbcReturn ret;
ret=libodbc.SQLAllocHandle((ushort) OdbcHandleType.Stmt, Connection.hDbc,
ref hstmt);
libodbc.DisplayError("SQLAlloc(Prepare)",ret);
ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
libodbc.DisplayError("SQLPrepare",ret);
prepared=true;
}
public OdbcDataReader ExecuteReader ()
{
return ExecuteReader (CommandBehavior.Default);
}
IDataReader IDbCommand.ExecuteReader ()
{
return ExecuteReader ();
}
public OdbcDataReader ExecuteReader (CommandBehavior behavior)
{
ExecuteNonQuery();
dataReader=new OdbcDataReader(this);
return dataReader;
}
IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
{
return ExecuteReader (behavior);
}
public object ExecuteScalar ()
{
throw new NotImplementedException ();
// if (connection.DataReader != null)
// throw new InvalidOperationException ();
//
}
[MonoTODO]
object ICloneable.Clone ()
{
throw new NotImplementedException ();
}
public void ResetCommandTimeout ()
{
timeout = 30;
}
#endregion
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcConnection.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcConnection.cs"
//
// System.Data.Odbc.OdbcConnection
//
// Authors:
// Brian Ritchie (brianlritchie@hotmail.com)
//
// Copyright (C) Brian Ritchie, 2002
//
using System.ComponentModel;
using System.Data;
using System.Data.Common;
namespace System.Data.Odbc
{
public sealed class OdbcConnection : Component, ICloneable, IDbConnection
{
#region Fields
string connectionString;
int connectionTimeout;
OdbcDataReader dataReader;
int henv=0, hdbc=0;
private string _uid, _pwd, _dsn;
#endregion
#region Constructors
public OdbcConnection ()
{
OdbcReturn ret;
// allocate Environment handle
ret=libodbc.SQLAllocHandle((ushort) OdbcHandleType.Env, 0, ref henv);
libodbc.DisplayError("SQLAllocHandle", ret);
ret=libodbc.SQLSetEnvAttr(henv, (ushort) OdbcEnv.OdbcVersion, (IntPtr) 3
, 0);
libodbc.DisplayError("SQLSetEnvAttr", ret);
Console.WriteLine("ODBCInit Complete.");
connectionTimeout = 15;
connectionString = null;
dataReader = null;
}
public OdbcConnection (string connectionString) : this ()
{
ConnectionString = connectionString;
}
#endregion // Constructors
#region Properties
public int hDbc
{
get { return hdbc; }
}
public string ConnectionString {
get {
return connectionString;
}
set {
connectionString = value;
string[] items=connectionString.Split(new char[1]{';'});
foreach (string item in items)
{
string[] parts=item.Split(new char[1] {'='});
switch (parts[0].Trim().ToLower())
{
case "dsn":
_dsn=parts[1].Trim();
break;
case "uid":
_uid=parts[1].Trim();
break;
case "pwd":
_pwd=parts[1].Trim();
break;
}
}
}
}
public int ConnectionTimeout {
get {
return connectionTimeout;
}
}
public string DataSource {
get {
if (State==ConnectionState.Open)
return _dsn;
else
return null;
}
}
public string Database {
get {
return "";
}
}
public ConnectionState State
{
get {
if (hdbc!=0) {
return ConnectionState.Open;
}
else
return ConnectionState.Closed;
}
}
internal OdbcDataReader DataReader
{
get {
return dataReader;
}
set {
dataReader = value;
}
}
#endregion // Properties
#region Methods
public void BeginTransaction()
{
OdbcReturn ret;
// Set Auto-commit to false
ret=libodbc.SQLSetConnectAttr(hdbc, 102, 0, 0);
libodbc.DisplayError("SQLSetConnectAttr(NoAutoCommit)", ret);
}
public void CommitTransaction()
{
OdbcReturn ret;
ret=libodbc.SQLEndTran((short) OdbcHandleType.Dbc, hdbc, 0);
libodbc.DisplayError("SQLEndTran(commit)", ret);
}
public void RollbackTransaction()
{
OdbcReturn ret;
ret=libodbc.SQLEndTran((short) OdbcHandleType.Dbc, hdbc, 1);
libodbc.DisplayError("SQLEndTran(rollback)", ret);
}
// public OdbcTransaction BeginTransaction ()
// {
// }
IDbTransaction IDbConnection.BeginTransaction ()
{
throw new NotImplementedException ();
// return BeginTransaction ();
}
// public OdbcTransaction BeginTransaction (IsolationLevel level)
// {
//
// }
IDbTransaction IDbConnection.BeginTransaction (IsolationLevel level)
{
throw new NotImplementedException ();
// return BeginTransaction (level);
}
public void Close ()
{
if (State == ConnectionState.Open) {
hdbc = 0;
}
dataReader = null;
}
public OdbcCommand CreateCommand ()
{
throw new NotImplementedException ();
}
[MonoTODO]
public void ChangeDatabase(string Database)
{
throw new NotImplementedException ();
}
[MonoTODO]
protected override void Dispose (bool disposing)
{
throw new NotImplementedException ();
}
[MonoTODO]
object ICloneable.Clone ()
{
throw new NotImplementedException();
}
IDbCommand IDbConnection.CreateCommand ()
{
throw new NotImplementedException();
// return CreateCommand ();
}
public void Open ()
{
if (State == ConnectionState.Open)
throw new InvalidOperationException ();
OdbcReturn ret;
// allocate connection handle
ret=libodbc.SQLAllocHandle((ushort) OdbcHandleType.Dbc, henv, ref hdbc);
libodbc.DisplayError("SQLAllocHandle(hdbc)", ret);
// Connect to data source
ret=libodbc.SQLConnect(hdbc, _dsn, -3, _uid, -3, _pwd, -3);
libodbc.DisplayError("SQLConnect",ret);
}
[MonoTODO]
public static void ReleaseObjectPool ()
{
throw new NotImplementedException ();
}
#endregion
#region Events and Delegates
public event StateChangeEventHandler StateChange;
#endregion
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcDataReader.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcDataReader.cs"
//
// System.Data.Odbc.OdbcDataReader
//
// Author:
// Brian Ritchie (brianlritchie@hotmail.com)
//
// Copyright (C) Brian Ritchie, 2002
//
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Runtime.InteropServices;
namespace System.Data.Odbc
{
public sealed class OdbcDataReader : MarshalByRefObject, IDataReader,
IDisposable, IDataRecord, IEnumerable
{
#region Fields
private OdbcCommand command;
private bool open;
private int currentRow;
private DataColumn[] cols;
private int hstmt;
#endregion
#region Constructors
internal OdbcDataReader (OdbcCommand command)
{
this.command = command;
this.command.Connection.DataReader = this;
open = true;
currentRow = -1;
hstmt=command.hStmt;
LoadColumns();
}
#endregion
#region Properties
public int Depth {
get {
return 0; // no nested selects supported
}
}
public int FieldCount {
get {
return cols.Length;
}
}
public bool IsClosed {
get {
return !open;
}
}
public DataColumn[] Columns
{
get {
return cols;
}
}
public object this[string name] {
get {
ushort pos;
if (currentRow == -1)
throw new InvalidOperationException ();
pos = ColIndex(name);
if (pos == -1)
throw new IndexOutOfRangeException ();
return this[pos];
}
}
public object this[int index] {
get {
return (object) GetODBCData (index);
}
}
public int RecordsAffected {
get {
return -1;
}
}
#endregion
#region Methods
private Type SQLTypeToCILType(short DataType)
{
switch (DataType)
{
case 12:
case 1:
return typeof(string);
case 4:
return typeof(int);
case 5:
return typeof(short);
case 2:
case 3:
case 6:
case 7:
case 8:
return typeof(float);
case 90:
case 91:
case 92:
case 9:
return typeof(DateTime);
default:
Console.WriteLine("WARNING: Unknown type {0}", DataType);
return typeof(string);
}
}
private short CILTypeToSQLType(Type type)
{
if (type==typeof(int))
return 4;
else if (type==typeof(string))
return 12;
else
return 12;
}
private void LoadColumns()
{
ArrayList colsArray=new ArrayList();
short colcount=0;
short bufsize=255;
byte[] colname_buffer=new byte[bufsize];
string colname;
short colname_size=0;
short DataType=0, ColSize=0, DecDigits=0, Nullable=0;
libodbc.SQLNumResultCols(hstmt, ref colcount);
for (ushort i=1;i<=colcount;i++)
{
libodbc.SQLDescribeCol(hstmt, i, colname_buffer, bufsize, ref
colname_size, ref DataType, ref ColSize, ref DecDigits, ref Nullable);
colname=System.Text.Encoding.Default.GetString(colname_buffer);
DataColumn c=new DataColumn(colname, SQLTypeToCILType(DataType));
c.AllowDBNull=(Nullable!=0);
if (c.DataType==typeof(string))
c.MaxLength=ColSize;
colsArray.Add(c);
}
cols=(DataColumn[]) colsArray.ToArray(typeof(DataColumn));
}
private ushort ColIndex(string colname)
{
ushort i=0;
foreach (DataColumn col in cols)
{
if (col.ColumnName==colname)
return i;
i++;
}
return 0;
}
private object GetODBCData(int colindex)
{
return GetODBCData(Convert.ToUInt16(colindex));
}
private object GetODBCData(ushort colindex)
{
OdbcReturn ret;
int outsize=0;
DataColumn col=cols[colindex];
colindex+=1;
if (col.DataType==typeof(int))
{
int data=0;
ret=libodbc.SQLGetData(hstmt, colindex, 4, ref data, 0, ref outsize);
libodbc.DisplayError("SQLGetData(int)",ret);
return data;
}
else if (col.DataType==typeof(string))
{
byte[] strbuffer=new byte[255];
ret=libodbc.SQLGetData(hstmt, colindex, 1, strbuffer, 255, ref outsize);
libodbc.DisplayError("SQLGetData("+col.ColumnName+","+colindex.ToString()+")",ret);
return System.Text.Encoding.Default.GetString(strbuffer);
}
else if (col.DataType==typeof(float))
{
float data=0;
ret=libodbc.SQLGetData(hstmt, colindex, 7, ref data, 0, ref outsize);
return data;
}
else if (col.DataType==typeof(DateTime))
{
OdbcTimestamp data=new OdbcTimestamp();
ret=libodbc.SQLGetData(hstmt, colindex, 91, ref data, 0, ref outsize);
return new
DateTime(data.year,data.month,data.day,data.hour,data.minute,data.second,Convert.ToInt32(data.fraction));
}
else return "";
}
public void Close ()
{
// libodbc.SQLFreeHandle((ushort) OdbcHandleType.Stmt, hstmt);
OdbcReturn ret=libodbc.SQLCloseCursor(hstmt);
libodbc.DisplayError("SQLCancel",ret);
open = false;
currentRow = -1;
this.command.Connection.DataReader = null;
}
~OdbcDataReader ()
{
if (open)
Close ();
}
public bool GetBoolean (int ordinal)
{
throw new NotImplementedException ();
}
public byte GetByte (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public long GetBytes (int ordinal, long dataIndex, byte[] buffer, int
bufferIndex, int length)
{
throw new NotImplementedException ();
}
public char GetChar (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public long GetChars (int ordinal, long dataIndex, char[] buffer, int
bufferIndex, int length)
{
throw new NotImplementedException ();
}
[MonoTODO]
public OdbcDataReader GetData (int ordinal)
{
throw new NotImplementedException ();
}
public string GetDataTypeName (int index)
{
return "";
}
public DateTime GetDateTime (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public decimal GetDecimal (int ordinal)
{
throw new NotImplementedException ();
}
public double GetDouble (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public Type GetFieldType (int index)
{
throw new NotImplementedException ();
}
public float GetFloat (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public Guid GetGuid (int ordinal)
{
throw new NotImplementedException ();
}
public short GetInt16 (int ordinal)
{
throw new NotImplementedException ();
}
public int GetInt32 (int ordinal)
{
throw new NotImplementedException ();
}
public long GetInt64 (int ordinal)
{
throw new NotImplementedException ();
}
public string GetName (int index)
{
if (currentRow == -1)
return null;
return cols[index].ColumnName;
}
public int GetOrdinal (string name)
{
if (currentRow == -1)
throw new IndexOutOfRangeException ();
int i=ColIndex(name);
if (i==-1)
throw new IndexOutOfRangeException ();
else
return i;
}
public DataTable GetSchemaTable ()
{
DataTable table = new DataTable ();
// FIXME: implement
return table;
}
public string GetString (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
public TimeSpan GetTimeSpan (int ordinal)
{
throw new NotImplementedException ();
}
public object GetValue (int ordinal)
{
if (currentRow == -1)
throw new IndexOutOfRangeException ();
if (ordinal>cols.Length-1 || ordinal<0)
throw new IndexOutOfRangeException ();
return (object) GetODBCData(ordinal);
}
[MonoTODO]
public int GetValues (object[] values)
{
throw new NotImplementedException ();
}
[MonoTODO]
IDataReader IDataRecord.GetData (int ordinal)
{
throw new NotImplementedException ();
}
[MonoTODO]
void IDisposable.Dispose ()
{
throw new NotImplementedException ();
}
[MonoTODO]
IEnumerator IEnumerable.GetEnumerator ()
{
throw new NotImplementedException ();
}
public bool IsDBNull (int ordinal)
{
throw new NotImplementedException ();
}
public bool NextResult ()
{
OdbcReturn ret=libodbc.SQLFetch(hstmt);
return (ret==OdbcReturn.Success);
}
public bool Read ()
{
return NextResult();
}
#endregion
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcParameter.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcParameter.cs"
//
// System.Data.Odbc.OdbcParameter
//
// Authors:
// Brian Ritchie (brianlritchie@hotmail.com)
//
// Copyright (C) Brian Ritchie, 2002
//
using System;
using System.Data;
using System.Data.Common;
namespace System.Data.Odbc
{
public sealed class OdbcParameter : MarshalByRefObject, IDbDataParameter,
IDataParameter, ICloneable
{
#region Fields
string name;
object value;
int size;
bool isNullable;
byte precision;
byte scale;
DataRowVersion sourceVersion;
string sourceColumn;
ParameterDirection direction;
OdbcType odbcType;
DbType dbType;
int IntValue;
#endregion
#region Constructors
public OdbcParameter ()
{
name = String.Empty;
value = null;
size = 0;
isNullable = true;
precision = 0;
scale = 0;
sourceColumn = String.Empty;
}
public OdbcParameter (string name, object value)
: this ()
{
this.name = name;
this.value = value;
}
public OdbcParameter (string name, OdbcType dataType)
: this ()
{
this.name = name;
OdbcType = dataType;
}
public OdbcParameter (string name, OdbcType dataType, int size)
: this (name, dataType)
{
this.size = size;
}
public OdbcParameter (string name, OdbcType dataType, int size, string
srcColumn)
: this (name, dataType, size)
{
this.sourceColumn = srcColumn;
}
public OdbcParameter(string name, OdbcType dataType, int size,
ParameterDirection direction, bool isNullable, byte precision, byte scale,
string srcColumn, DataRowVersion srcVersion, object value)
: this (name, dataType, size, srcColumn)
{
this.direction = direction;
this.isNullable = isNullable;
this.precision = precision;
this.scale = scale;
this.sourceVersion = srcVersion;
this.value = value;
}
#endregion
#region Properties
public DbType DbType {
get { return dbType; }
set {
dbType = value;
}
}
public ParameterDirection Direction {
get { return direction; }
set { direction = value; }
}
public bool IsNullable {
get { return isNullable; }
}
public OdbcType OdbcType {
get { return odbcType; }
set {
odbcType = value;
}
}
public string ParameterName {
get { return name; }
set { name = value; }
}
public byte Precision {
get { return precision; }
set { precision = value; }
}
public byte Scale {
get { return scale; }
set { scale = value; }
}
public int Size {
get { return size; }
set { size = value; }
}
public string SourceColumn {
get { return sourceColumn; }
set { sourceColumn = value; }
}
public DataRowVersion SourceVersion {
get { return sourceVersion; }
set { sourceVersion = value; }
}
public object Value {
get {
return IntValue;
}
set { this.IntValue =(int) value; }
}
#endregion // Properties
#region Internal Properties
internal void Bind(int hstmt,int ParamNum)
{
if (OdbcType==OdbcType.Integer)
{
OdbcReturn ret=libodbc.SQLBindParam(hstmt, Convert.ToInt16(ParamNum), 4,
4, 0,0,ref IntValue, 0);
libodbc.DisplayError("SQLBindParam",ret);
}
else Console.WriteLine("Unknown Paramter Type");
}
#endregion // Internal Properties
#region Methods
[MonoTODO]
object ICloneable.Clone ()
{
throw new NotImplementedException ();
}
public override string ToString ()
{
return ParameterName;
}
#endregion
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcParameterCollection.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcParameterCollection.cs"
//
// System.Data.Odbc.OdbcParameterCollection
//
// Author:
// Brian Ritchie (brianlritchie@hotmail.com)
//
// Copyright (C) Brian Ritchie, 2002
//
using System.Collections;
using System.Data;
using System.Data.Common;
namespace System.Data.Odbc
{
public sealed class OdbcParameterCollection : MarshalByRefObject,
IDataParameterCollection, IList, ICollection, IEnumerable
{
#region Fields
ArrayList list = new ArrayList ();
#endregion // Fields
#region Properties
public int Count {
get { return list.Count; }
}
public OdbcParameter this[int index] {
get { return (OdbcParameter) list[index]; }
set { list[index] = value; }
}
public OdbcParameter this[string parameterName] {
[MonoTODO]
get { throw new NotImplementedException (); }
[MonoTODO]
set { throw new NotImplementedException (); }
}
int ICollection.Count {
get { return list.Count; }
}
bool IList.IsFixedSize {
get { return false; }
}
bool IList.IsReadOnly {
get { return false; }
}
bool ICollection.IsSynchronized {
get { return list.IsSynchronized; }
}
object ICollection.SyncRoot {
get { return list.SyncRoot; }
}
object IList.this[int index] {
get { return list[index]; }
set { list[index] = value; }
}
object IDataParameterCollection.this[string name]
{
[MonoTODO]
get {
throw new NotImplementedException ();
}
[MonoTODO]
set {
throw new NotImplementedException ();
}
}
#endregion // Properties
#region Methods
public OdbcParameter Add (OdbcParameter parameter)
{
list.Add (parameter);
return parameter;
}
public OdbcParameter Add (string name, object value)
{
OdbcParameter parameter = new OdbcParameter (name, value);
list.Add (parameter);
return parameter;
}
public OdbcParameter Add (string name, OdbcType type)
{
OdbcParameter parameter = new OdbcParameter (name, type);
list.Add (parameter);
return parameter;
}
public OdbcParameter Add (string name, OdbcType type, int width)
{
OdbcParameter parameter = new OdbcParameter (name, type, width);
list.Add (parameter);
return parameter;
}
public OdbcParameter Add (string name, OdbcType type,
int width, string src_col)
{
OdbcParameter parameter = new OdbcParameter (name, type, width, src_col);
list.Add (parameter);
return parameter;
}
internal void Bind(int hstmt)
{
for (int i=0;i<Count;i++)
{
this[i].Bind(hstmt,i+1);
}
}
int IList.Add (object value)
{
if (!(value is IDataParameter))
throw new InvalidCastException ();
list.Add (value);
return list.IndexOf (value);
}
void IList.Clear ()
{
list.Clear ();
}
bool IList.Contains (object value)
{
return list.Contains (value);
}
bool IDataParameterCollection.Contains (string value)
{
for (int i = 0; i < list.Count; i++) {
IDataParameter parameter;
parameter = (IDataParameter) list[i];
if (parameter.ParameterName == value)
return true;
}
return false;
}
void ICollection.CopyTo (Array array, int index)
{
((OdbcParameter[])(list.ToArray ())).CopyTo (array, index);
}
IEnumerator IEnumerable.GetEnumerator ()
{
return list.GetEnumerator ();
}
int IList.IndexOf (object value)
{
return list.IndexOf (value);
}
int IDataParameterCollection.IndexOf (string name)
{
return list.IndexOf (((IDataParameterCollection) this)[name]);
}
void IList.Insert (int index, object value)
{
list.Insert (index, value);
}
void IList.Remove (object value)
{
list.Remove (value);
}
void IList.RemoveAt (int index)
{
list.Remove ((object) list[index]);
}
void IDataParameterCollection.RemoveAt (string name)
{
list.Remove (((IDataParameterCollection) this)[name]);
}
#endregion // Methods
}
}
------=_NextPart_000_1137_7ffa_3c09
Content-Type: text/plain; name="OdbcType.cs"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="OdbcType.cs"
//
// System.Data.Odbc.OdbcType
//
// Author:
// Brian Ritchie
//
// Copyright (C) Brian Ritchie, 2002
//
using System.Data;
using System.Data.Common;
namespace System.Data.Odbc
{
public enum OdbcType {
BigInt,
Binary,
Boolean,
BSTR,
Char,
Currency,
Date,
DBDate,
DBTime,
DBTimeStamp,
Decimal,
Double,
Empty,
Error,
Filetime,
Guid,
IDispatch,
Integer,
IUnknown,
LongVarBinary,
LongVarChar,
LongVarWChar,
Numeric,
PropVariant,
Single,
SmallInt,
TinyInt,
UnsignedBigInt,
UnsignedInt,
UnsignedSmallInt,
UnsignedTinyInt,
VarBinary,
VarChar,
Variant,
VarNumeric,
VarWChar,
WChar
}
}
------=_NextPart_000_1137_7ffa_3c09--