2003-12-13 Tim Coleman <tim@timcoleman.com>
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient / OracleConnection.cs
1 //
2 // OracleConnection.cs 
3 //
4 // Part of the Mono class libraries at
5 // mcs/class/System.Data.OracleClient/System.Data.OracleClient
6 //
7 // Assembly: System.Data.OracleClient.dll
8 // Namespace: System.Data.OracleClient
9 //
10 // Authors: 
11 //    Daniel Morgan <danmorg@sc.rr.com>
12 //    Tim Coleman <tim@timcoleman.com>
13 //
14 // Copyright (C) Daniel Morgan, 2002
15 // Copyright (C) Tim Coleman, 2003
16 //
17 // Original source code for setting ConnectionString 
18 // by Tim Coleman <tim@timcoleman.com>
19 //
20 // Copyright (C) Tim Coleman, 2002
21 //
22 // Licensed under the MIT/X11 License.
23 //
24
25 using System;
26 using System.Collections;
27 using System.Collections.Specialized;
28 using System.ComponentModel;
29 using System.Data;
30 using System.Data.OracleClient.Oci;
31 using System.Text;
32
33 namespace System.Data.OracleClient 
34 {
35         internal struct OracleConnectionInfo 
36         {
37                 public string Username;
38                 public string Password;
39                 public string Database;
40         }
41
42         public class OracleConnection : Component, ICloneable, IDbConnection
43         {
44                 #region Fields
45
46                 OciGlue oci;
47                 ConnectionState state;
48                 OracleConnectionInfo conInfo;
49                 OracleTransaction transaction = null;
50                 string connectionString = "";
51                 OracleDataReader dataReader = null;
52
53                 #endregion // Fields
54
55                 #region Constructors
56
57                 public OracleConnection () 
58                 {
59                         state = ConnectionState.Closed;
60                         oci = new OciGlue ();
61                 }
62
63                 public OracleConnection (string connectionString) 
64                         : this() 
65                 {
66                         this.connectionString = connectionString;
67                 }
68
69                 #endregion // Constructors
70
71                 #region Properties
72
73                 // only for DEBUG purposes - not part of MS.NET 1.1 OracleClient
74                 public static uint ConnectionCount {
75                         get {
76                                 uint count = 0; // OciGlue.OciGlue_ConnectionCount();
77                                 return count;
78                         }
79                 }
80
81                 int IDbConnection.ConnectionTimeout {
82                         [MonoTODO]
83                         get { return -1; }
84                 }
85
86                 string IDbConnection.Database {
87                         [MonoTODO]
88                         get { return String.Empty; }
89                 }
90
91                 internal OracleDataReader DataReader {
92                         get { return dataReader; }
93                         set { dataReader = value; }
94                 }
95
96                 public ConnectionState State {
97                         get { return state; }
98                 }
99
100                 public string ConnectionString {
101                         get { return connectionString; }
102                         set { SetConnectionString (value); }
103                 }
104
105                 internal OciGlue Oci {
106                         get { return oci; }
107                 }
108
109                 internal OracleTransaction Transaction {
110                         get { return transaction; }
111                         set { transaction = value; }
112                 }
113
114                 #endregion // Properties
115
116                 #region Methods
117
118                 public OracleTransaction BeginTransaction ()
119                 {
120                         return BeginTransaction (IsolationLevel.ReadCommitted);
121                 }
122
123                 public OracleTransaction BeginTransaction (IsolationLevel il)
124                 {
125                         if (state == ConnectionState.Closed)
126                                 throw new InvalidOperationException ("The connection is not open.");
127                         if (transaction != null)
128                                 throw new InvalidOperationException ("OracleConnection does not support parallel transactions.");
129
130                         OciTransactionHandle transactionHandle = oci.CreateTransaction ();
131                         if (transactionHandle == null) 
132                                 throw new Exception("Error: Unable to start transaction");
133                         else {
134                                 transactionHandle.Begin ();
135                                 transaction = new OracleTransaction (this, il, transactionHandle);
136                         }
137
138                         return transaction;
139                 }
140
141                 [MonoTODO]
142                 void IDbConnection.ChangeDatabase (string databaseName)
143                 {
144                         throw new NotImplementedException ();
145                 }
146
147                 public OracleCommand CreateCommand ()
148                 {
149                         OracleCommand command = new OracleCommand ();
150                         command.Connection = this;
151                         return command;
152                 }
153
154                 [MonoTODO]
155                 object ICloneable.Clone ()
156                 {
157                         throw new NotImplementedException ();
158                 }
159
160                 IDbTransaction IDbConnection.BeginTransaction ()
161                 {
162                         return BeginTransaction ();
163                 }
164
165                 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
166                 {
167                         return BeginTransaction (iso);
168                 }
169
170                 IDbCommand IDbConnection.CreateCommand ()
171                 {
172                         return CreateCommand ();
173                 }
174
175                 void IDisposable.Dispose ()
176                 {
177                         Dispose (true);
178                         GC.SuppressFinalize (this);
179                 }
180
181                 public void Open () 
182                 {
183                         oci.CreateConnection (conInfo);
184                         state = ConnectionState.Open;
185                 }
186
187                 public void Close () 
188                 {
189                         oci.Disconnect();
190                         state = ConnectionState.Closed;
191                 }
192
193
194                 void SetConnectionString (string connectionString) 
195                 {
196                         this.connectionString = connectionString;
197                         conInfo.Username = "";
198                         conInfo.Database = "";
199                         conInfo.Password = "";
200
201                         if (connectionString == String.Empty)
202                                 return;
203                         
204                         connectionString += ";";
205                         NameValueCollection parameters = new NameValueCollection ();
206
207                         bool inQuote = false;
208                         bool inDQuote = false;
209
210                         string name = String.Empty;
211                         string value = String.Empty;
212                         StringBuilder sb = new StringBuilder ();
213
214                         foreach (char c in connectionString) {
215                                 switch (c) {
216                                 case '\'':
217                                         inQuote = !inQuote;
218                                         break;
219                                 case '"' :
220                                         inDQuote = !inDQuote;
221                                         break;
222                                 case ';' :
223                                         if (!inDQuote && !inQuote) {
224                                                 if (name != String.Empty && name != null) {
225                                                         value = sb.ToString ();
226                                                         parameters [name.ToUpper ().Trim ()] = value.Trim ();
227                                                 }
228                                                 name = String.Empty;
229                                                 value = String.Empty;
230                                                 sb = new StringBuilder ();
231                                         }
232                                         else
233                                                 sb.Append (c);
234                                         break;
235                                 case '=' :
236                                         if (!inDQuote && !inQuote) {
237                                                 name = sb.ToString ();
238                                                 sb = new StringBuilder ();
239                                         }
240                                         else
241                                                 sb.Append (c);
242                                         break;
243                                 default:
244                                         sb.Append (c);
245                                         break;
246                                 }
247                         }
248
249                         SetProperties (parameters);
250                 }
251
252                 private void SetProperties (NameValueCollection parameters) 
253                 {       
254                         string value;
255                         foreach (string name in parameters) {
256                                 value = parameters[name];
257
258                                 switch (name) {
259                                 case "DATA SOURCE" :
260                                 case "DATABASE" :
261                                         // set Database property
262                                         conInfo.Database = value;
263                                         break;
264                                 case "PASSWORD" :
265                                 case "PWD" :
266                                         conInfo.Password = value;
267                                         break;
268                                 case "UID" :
269                                 case "USER ID" :
270                                         conInfo.Username = value;
271                                         break;
272                                 default:
273                                         throw new Exception("Connection parameter not supported." + name);
274                                 }
275                         }
276                 }
277
278                 #endregion // Methods
279         }
280 }