2 // System.Data.SqlClient.SqlConnection.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
8 // (C) Ximian, Inc 2002
11 // use #define DEBUG_SqlConnection if you want to spew debug messages
12 // #define DEBUG_SqlConnection
15 using System.ComponentModel;
17 using System.Data.Common;
18 using System.Runtime.InteropServices;
21 namespace System.Data.SqlClient
23 // using PGconn = IntPtr;
24 // PGconn is native C library type in libpq for Postgres Connection
26 // using PGressult = IntPtr;
27 // PGresult is native C library type in libpq for Postgres Resultset
30 /// Represents an open connection to a SQL data source
32 //public sealed class SqlConnection : Component, IDbConnection,
34 public sealed class SqlConnection : IDbConnection
36 // FIXME: Need to implement class Component,
\r
37 // and interfaces: ICloneable and IDisposable
41 private IntPtr pgConn = IntPtr.Zero;
42 // PGConn (Postgres Connection)
43 private string connectionString = "";
44 // OLE DB Connection String
45 private string pgConnectionString = "";
46 // PostgreSQL Connection String
47 private SqlTransaction trans = null;
48 private int connectionTimeout = 15;
49 // default for 15 seconds
51 // connection parameters in connection string
52 private string host = "";
53 // Name of host to connect to
54 private string hostaddr = "";
55 // IP address of host to connect to
56 // should be in "n.n.n.n" format
57 private string port = "";
58 // Port number to connect to at the server host
59 private string dbname = ""; // The database name.
60 private string user = ""; // User name to connect as.
61 private string password = "";
62 // Password to be used if the server
63 // demands password authentication.
64 private string options = "";
65 // Trace/debug options to be sent to the server.
66 private string tty = "";
67 // A file or tty for optional
68 // debug output from the backend.
69 private string requiressl = "";
70 // Set to 1 to require
71 // SSL connection to the backend.
72 // Libpq will then refuse to connect
73 // if the server does not
74 // support SSL. Set to 0 (default) to
75 // negotiate with server.
77 ConnectionState conState = ConnectionState.Closed;
85 public SqlConnection ()
87 this.ConnectionString = null;
88 this.ConnectionTimeout = 0;
94 public SqlConnection (string cs) : SqlConnection ()
96 this.ConnectionString = cs;
100 // A lot of the defaults were initialized in the Fields
102 public SqlConnection ()
108 public SqlConnection (String connectionString)
110 SetConnectionString (connectionString);
113 #endregion // Constructors
118 public void Dispose () {
119 // FIXME: release resources properly
125 // [ClassInterface(ClassInterfaceType.AutoDual)]
129 // FIXME: this class need
130 // a destructor to release resources
131 // Also, take a look at Dispose
135 #endregion // Destructors
137 #region Public Methods
139 IDbTransaction IDbConnection.BeginTransaction ()
141 return BeginTransaction ();
144 public SqlTransaction BeginTransaction ()
146 return TransactionBegin (); // call private method
149 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel
152 return BeginTransaction (il);
155 public SqlTransaction BeginTransaction (IsolationLevel il)
157 return TransactionBegin (il); // call private method
160 // PostgreSQL does not support named transactions/savepoint
161 // nor nested transactions
163 public SqlTransaction BeginTransaction(string transactionName) {
164 return TransactionBegin (); // call private method
168 public SqlTransaction BeginTransaction(IsolationLevel iso,
\r
169 string transactionName) {
170 return TransactionBegin (iso); // call private method
174 public void ChangeDatabase (string databaseName)
176 throw new NotImplementedException ();
185 IDbCommand IDbConnection.CreateCommand ()
187 return CreateCommand ();
190 public SqlCommand CreateCommand ()
192 SqlCommand sqlcmd = new SqlCommand ("", this);
203 #endregion // Public Methods
205 #region Internal Methods
207 // this is for System.Data.SqlClient classes
208 // to get the Postgres connection
209 internal IntPtr PostgresConnection {
215 #endregion // Internal Methods
217 #region Protected Methods
219 // FIXME: protected override void Dispose overrides Component
220 // however, including Component causes other problems
223 protected override void Dispose (bool disposing)
225 throw new NotImplementedException ();
231 #region Private Methods
233 private void OpenDataSource ()
235 if(dbname.Equals(""))
236 throw new InvalidOperationException(
238 else if(conState == ConnectionState.Open)
239 throw new InvalidOperationException(
240 "ConnnectionState is already Open");
242 ConnStatusType connStatus;
244 // FIXME: check to make sure we have
245 // everything to connect,
246 // otherwise, throw an exception
248 pgConn = PostgresLibrary.PQconnectdb
249 (pgConnectionString);
251 // FIXME: should we use PQconnectStart/PQconnectPoll
252 // instead of PQconnectdb?
253 // PQconnectdb blocks
254 // PQconnectStart/PQconnectPoll is non-blocking
256 connStatus = PostgresLibrary.PQstatus (pgConn);
257 if(connStatus == ConnStatusType.CONNECTION_OK)
259 // Successfully Connected
260 conState = ConnectionState.Open;
264 String errorMessage = PostgresLibrary.
265 PQerrorMessage (pgConn);
266 errorMessage += ": Could not connect to database.";
268 throw new SqlException(0, 0,
270 host, "SqlConnection", 0);
274 private void CloseDataSource ()
276 // FIXME: just a quick hack
277 conState = ConnectionState.Closed;
278 PostgresLibrary.PQfinish (pgConn);
281 private void SetConnectionString (string connectionString)
283 // FIXME: perform error checking on string
284 // while translating string from
285 // OLE DB format to PostgreSQL
286 // connection string format
288 // OLE DB: "host=localhost;dbname=test;user=joe;password=smoe"
289 // PostgreSQL: "host=localhost dbname=test user=joe password=smoe"
291 // For OLE DB, you would have the additional
292 // "provider=postgresql"
293 // OleDbConnection you would be using libgda, maybe
295 // "provider=OAFIID:GNOME_Database_Postgres_Provider"
298 // Also, parse the connection string into properties
300 // FIXME: if connection is open, you can
301 // not set the connection
302 // string, throw an exception
304 this.connectionString = connectionString;
305 pgConnectionString = ConvertStringToPostgres (
308 #if DEBUG_SqlConnection
310 "OLE-DB Connection String [in]: " +
311 this.ConnectionString);
313 "Postgres Connection String [out]: " +
315 #endif // DEBUG_SqlConnection
318 private String ConvertStringToPostgres (String
319 oleDbConnectionString)
321 StringBuilder postgresConnection =
324 string[] connectionParameters;
326 char[] semicolon = new Char[1];
329 // FIXME: what is the max number of value pairs
330 // can there be for the OLE DB
331 // connnection string? what about libgda max?
332 // what about postgres max?
334 // FIXME: currently assuming value pairs are like:
335 // "key1=value1;key2=value2;key3=value3"
336 // Need to deal with values that have
337 // single or double quotes. And error
338 // handling of that too.
339 // "key1=value1;key2='value2';key=\"value3\""
341 // FIXME: put the connection parameters
342 // from the connection
344 // Hashtable (System.Collections)
345 // instead of using private variables
347 connectionParameters = oleDbConnectionString.
349 foreach (string sParameter in connectionParameters) {
350 if(sParameter.Length > 0) {
351 BreakConnectionParameter (sParameter);
357 result = postgresConnection.ToString ();
361 private bool BreakConnectionParameter (String sParameter)
366 index = sParameter.IndexOf ("=");
368 string parmKey, parmValue;
370 // separate string "key=value" to
371 // string "key" and "value"
372 parmKey = sParameter.Substring (0, index);
373 parmValue = sParameter.Substring (index + 1,
374 sParameter.Length - index - 1);
376 switch(parmKey.ToLower()) {
378 hostaddr = parmValue;
386 // set DataSource property
391 // set Database property
400 password = parmValue;
413 requiressl = parmValue;
420 private SqlTransaction TransactionBegin ()
422 // FIXME: need to keep track of
423 // transaction in-progress
424 trans = new SqlTransaction ();
425 // using internal methods of SqlTransaction
426 trans.SetConnection (this);
432 private SqlTransaction TransactionBegin (IsolationLevel il)
434 // FIXME: need to keep track of
435 // transaction in-progress
437 trans.SetIsolationLevel (il);
447 public ConnectionState State {
453 public string ConnectionString {
455 return connectionString;
458 SetConnectionString (value);
462 public int ConnectionTimeout {
464 return connectionTimeout;
468 public string Database {
474 public string DataSource {
481 * FIXME: this is here because of Component?
483 protected bool DesignMode {
485 throw new NotImplementedException ();
489 public int PacketSize {
491 throw new NotImplementedException ();
495 public string ServerVersion {
497 throw new NotImplementedException ();
501 internal SqlTransaction Transaction {
509 #region Events and Delegates
511 // FIXME: the two events belong here
512 // however, i do not know about the delegates
513 // also, they are stubs for now
516 SqlInfoMessageEventHandler (object sender,
517 SqlInfoMessageEventArgs e);
520 SqlInfoMessageEventHandler InfoMessage;
523 StateChangeEventHandler StateChange;