| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- //
- // System.Data.SqlClient.SqlConnection.cs
- //
- // Author:
- // Rodrigo Moya ([email protected])
- // Daniel Morgan ([email protected])
- //
- // (C) Ximian, Inc 2002
- //
- // use #define DEBUG_SqlConnection if you want to spew debug messages
- // #define DEBUG_SqlConnection
- using System;
- using System.ComponentModel;
- using System.Data;
- using System.Data.Common;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace System.Data.SqlClient
- {
- using PGconn = IntPtr;
- // PGconn is native C library type in libpq for Postgres Connection
- // using PGressult = IntPtr;
- // PGresult is native C library type in libpq for Postgres Resultset
- /// <summary>
- /// Represents an open connection to a SQL data source
- /// </summary>
- //public sealed class SqlConnection : Component, IDbConnection,
- // ICloneable
- public sealed class SqlConnection : IDbConnection
- {
- // FIXME: Need to implement class Component,
- // and interfaces: ICloneable and IDisposable
- #region Fields
- private PGconn pgConn = IntPtr.Zero;
- // PGConn (Postgres Connection)
- private string connectionString = "";
- // OLE DB Connection String
- private string pgConnectionString = "";
- // PostgreSQL Connection String
- private SqlTransaction trans = null;
- private int connectionTimeout = 15;
- // default for 15 seconds
-
- // connection parameters in connection string
- private string host = "";
- // Name of host to connect to
- private string hostaddr = "";
- // IP address of host to connect to
- // should be in "n.n.n.n" format
- private string port = "";
- // Port number to connect to at the server host
- private string dbname = ""; // The database name.
- private string user = ""; // User name to connect as.
- private string password = "";
- // Password to be used if the server
- // demands password authentication.
- private string options = "";
- // Trace/debug options to be sent to the server.
- private string tty = "";
- // A file or tty for optional
- // debug output from the backend.
- private string requiressl = "";
- // Set to 1 to require
- // SSL connection to the backend.
- // Libpq will then refuse to connect
- // if the server does not
- // support SSL. Set to 0 (default) to
- // negotiate with server.
- ConnectionState conState = ConnectionState.Closed;
- #endregion // Fields
- #region Constructors
- /*
- [MonoTODO]
- public SqlConnection ()
- {
- this.ConnectionString = null;
- this.ConnectionTimeout = 0;
- this.Database = null;
- this.State = 0;
- }
-
- [MonoTODO]
- public SqlConnection (string cs) : SqlConnection ()
- {
- this.ConnectionString = cs;
- }
-
- */
- // A lot of the defaults were initialized in the Fields
- [MonoTODO]
- public SqlConnection ()
- {
- }
-
- [MonoTODO]
- public SqlConnection (String connectionString)
- {
- SetConnectionString (connectionString);
- }
- #endregion // Constructors
- #region Destructors
- [MonoTODO]
- public void Dispose () {
- // FIXME: release resources properly
- Close ();
- // Dispose (true);
- }
-
- // aka Finalize
- // [ClassInterface(ClassInterfaceType.AutoDual)]
- [MonoTODO]
- ~SqlConnection()
- {
- // FIXME: this class need
- // a destructor to release resources
- // Also, take a look at Dispose
- // Dispose (false);
- }
-
- #endregion // Destructors
- #region Public Methods
- IDbTransaction IDbConnection.BeginTransaction ()
- {
- return BeginTransaction ();
- }
- public SqlTransaction BeginTransaction ()
- {
- return TransactionBegin (); // call private method
- }
- IDbTransaction IDbConnection.BeginTransaction (IsolationLevel
- il)
- {
- return BeginTransaction (il);
- }
- public SqlTransaction BeginTransaction (IsolationLevel il)
- {
- return TransactionBegin (il); // call private method
- }
- // PostgreSQL does not support named transactions/savepoint
- // nor nested transactions
- [Obsolete]
- public SqlTransaction BeginTransaction( string transactionName) {
- return TransactionBegin (); // call private method
- }
- [Obsolete]
- public SqlTransaction BeginTransaction(IsolationLevel iso,
- string transactionName) {
- return TransactionBegin (); // call private method
- }
- [MonoTODO]
- public void ChangeDatabase (string databaseName)
- {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- public void Close ()
- {
- CloseDataSource ();
- }
- IDbCommand IDbConnection.CreateCommand ()
- {
- return CreateCommand ();
- }
- public SqlCommand CreateCommand ()
- {
- SqlCommand sqlcmd = new SqlCommand ("", this);
- return sqlcmd;
- }
- [MonoTODO]
- public void Open ()
- {
- OpenDataSource ();
- }
- #endregion // Public Methods
- #region Internal Methods
- // this is for System.Data.SqlClient classes
- // to get the Postgres connection
- internal IntPtr PostgresConnection {
- get {
- return pgConn;
- }
- }
- #endregion // Internal Methods
- #region Protected Methods
- // FIXME: protected override void Dispose overrides Component
- // however, including Component causes other problems
- /*
- [MonoTODO]
- protected override void Dispose (bool disposing)
- {
- throw new NotImplementedException ();
- }
- */
- #endregion
- #region Private Methods
- private void OpenDataSource ()
- {
- if(dbname.Equals(""))
- throw new InvalidOperationException("dbname missing");
- else if(conState == ConnectionState.Open)
- throw new InvalidOperationException("ConnnectionState is already Open");
- ConnStatusType connStatus;
- // FIXME: check to make sure we have
- // everything to connect,
- // otherwise, throw an exception
- pgConn = PostgresLibrary.PQconnectdb
- (pgConnectionString);
- // FIXME: should we use PQconnectStart/PQconnectPoll
- // instead of PQconnectdb?
- // PQconnectdb blocks
- // PQconnectStart/PQconnectPoll is non-blocking
-
- connStatus = PostgresLibrary.PQstatus (pgConn);
- if(connStatus == ConnStatusType.CONNECTION_OK)
- {
- // Successfully Connected
- conState = ConnectionState.Open;
- }
- else
- {
- String errorMessage = PostgresLibrary.
- PQerrorMessage (pgConn);
- errorMessage += ": Could not connect to database.";
- throw new SqlException(0, 0,
- errorMessage, 0, "",
- host, "SqlConnection", 0);
- }
- }
- private void CloseDataSource ()
- {
- // FIXME: just a quick hack
- conState = ConnectionState.Closed;
- PostgresLibrary.PQfinish (pgConn);
- }
- private void SetConnectionString (string connectionString)
- {
- // FIXME: perform error checking on string
- // while translating string from
- // OLE DB format to PostgreSQL
- // connection string format
- //
- // OLE DB: "host=localhost;dbname=test;user=joe;password=smoe"
- // PostgreSQL: "host=localhost dbname=test user=joe password=smoe"
- //
- // For OLE DB, you would have the additional
- // "provider=postgresql"
- // OleDbConnection you would be using libgda, maybe
- // it would be
- // "provider=OAFIID:GNOME_Database_Postgres_Provider"
- // instead.
- //
- // Also, parse the connection string into properties
- // FIXME: if connection is open, you can
- // not set the connection
- // string, throw an exception
- this.connectionString = connectionString;
- pgConnectionString = ConvertStringToPostgres (
- connectionString);
- #if DEBUG_SqlConnection
- Console.WriteLine(
- "OLE-DB Connection String [in]: " +
- this.ConnectionString);
- Console.WriteLine(
- "Postgres Connection String [out]: " +
- pgConnectionString);
- #endif // DEBUG_SqlConnection
- }
- private String ConvertStringToPostgres (String
- oleDbConnectionString)
- {
- StringBuilder postgresConnection =
- new StringBuilder();
- string result;
- string[] connectionParameters;
- char[] semicolon = new Char[1];
- semicolon[0] = ';';
-
- // FIXME: what is the max number of value pairs
- // can there be for the OLE DB
- // connnection string? what about libgda max?
- // what about postgres max?
- // FIXME: currently assuming value pairs are like:
- // "key1=value1;key2=value2;key3=value3"
- // Need to deal with values that have
- // single or double quotes. And error
- // handling of that too.
- // "key1=value1;key2='value2';key=\"value3\""
- // FIXME: put the connection parameters
- // from the connection
- // string into a
- // Hashtable (System.Collections)
- // instead of using private variables
- // to store them
- connectionParameters = oleDbConnectionString.
- Split (semicolon);
- foreach (string sParameter in connectionParameters) {
- if(sParameter.Length > 0) {
- BreakConnectionParameter (sParameter);
- postgresConnection.
- Append (sParameter +
- " ");
- }
- }
- result = postgresConnection.ToString ();
- return result;
- }
- private bool BreakConnectionParameter (String sParameter)
- {
- bool addParm = true;
- int index;
- index = sParameter.IndexOf ("=");
- if (index > 0) {
- string parmKey, parmValue;
- // separate string "key=value" to
- // string "key" and "value"
- parmKey = sParameter.Substring (0, index);
- parmValue = sParameter.Substring (index + 1,
- sParameter.Length - index - 1);
- switch(parmKey.ToLower()) {
- case "host":
- // set DataSource property
- host = parmValue;
- break;
- case "dbname":
- // set Database property
- dbname = parmValue;
- break;
- case "user":
- user = parmValue;
- break;
- case "password":
- password = parmValue;
- // addParm = false;
- break;
- case "options":
- options = parmValue;
- break;
- case "tty":
- tty = parmValue;
- break;
-
- case "requiressl":
- requiressl = parmValue;
- break;
- }
- }
- return addParm;
- }
- private SqlTransaction TransactionBegin ()
- {
- // FIXME: need to keep track of
- // transaction in-progress
- trans = new SqlTransaction ();
- // using internal methods of SqlTransaction
- trans.SetConnection (this);
- trans.Begin();
- return trans;
- }
- private SqlTransaction TransactionBegin (IsolationLevel il)
- {
- // FIXME: need to keep track of
- // transaction in-progress
- TransactionBegin();
- trans.SetIsolationLevel (il);
-
- return trans;
- }
- #endregion
- #region Properties
- [MonoTODO]
- public ConnectionState State {
- get {
- return conState;
- }
- }
- public string ConnectionString {
- get {
- return connectionString;
- }
- set {
- SetConnectionString (value);
- }
- }
-
- public int ConnectionTimeout {
- get {
- return connectionTimeout;
- }
- }
- public string Database {
- get {
- return dbname;
- }
- }
- public string DataSource {
- get {
- return host;
- }
- }
- /*
- * FIXME: this is here because of Component?
- [MonoTODO]
- protected bool DesignMode {
- get {
- throw new NotImplementedException ();
- }
- }
- */
- public int PacketSize {
- get {
- throw new NotImplementedException ();
- }
- }
- public string ServerVersion {
- get {
- throw new NotImplementedException ();
- }
- }
- internal SqlTransaction Transaction {
- get {
- return trans;
- }
- }
- #endregion
- #region Events and Delegates
-
- // FIXME: the two events belong here
- // however, i do not know about the delegates
- // also, they are stubs for now
- /*
- public delegate void
- SqlInfoMessageEventHandler (object sender,
- SqlInfoMessageEventArgs e);
- public event
- SqlInfoMessageEventHandler InfoMessage;
- public event
- StateChangeEventHandler StateChange;
- */
- #endregion
- }
- }
|