2 // Mono.Data.Sqlite.SqliteConnection.cs
4 // Represents an open connection to a Sqlite database file.
6 // Author(s): Vladimir Vukicevic <vladimir@pobox.com>
7 // Everaldo Canuto <everaldo_canuto@yahoo.com.br>
9 // Copyright (C) 2002 Vladimir Vukicevic
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Runtime.InteropServices;
37 namespace Mono.Data.Sqlite
39 public class SqliteConnection : IDbConnection, ICloneable
44 private string conn_str;
45 private string db_file;
47 private int db_version;
48 private IntPtr sqlite_handle;
49 private ConnectionState state;
50 private Encoding encoding;
51 private int busy_timeout;
55 #region Constructors and destructors
57 public SqliteConnection ()
62 state = ConnectionState.Closed;
63 sqlite_handle = IntPtr.Zero;
68 public SqliteConnection (string connstring) : this ()
70 ConnectionString = connstring;
73 public void Dispose ()
82 public string ConnectionString {
83 get { return conn_str; }
84 set { SetConnectionString(value); }
87 public int ConnectionTimeout {
91 public string Database {
92 get { return db_file; }
95 public ConnectionState State {
99 public Encoding Encoding {
100 get { return encoding; }
104 get { return db_version; }
107 internal IntPtr Handle {
108 get { return sqlite_handle; }
111 public int LastInsertRowId {
114 return (int)Sqlite.sqlite3_last_insert_rowid (Handle);
116 return Sqlite.sqlite_last_insert_rowid (Handle);
120 public int BusyTimeout {
125 busy_timeout = value < 0 ? 0 : value;
131 #region Private Methods
133 private void SetConnectionString(string connstring)
135 if (connstring == null) {
141 if (connstring != conn_str) {
143 conn_str = connstring;
148 string[] conn_pieces = connstring.Split (',');
149 for (int i = 0; i < conn_pieces.Length; i++) {
150 string piece = conn_pieces [i].Trim ();
151 if (piece.Length == 0) { // ignore empty elements
154 string[] arg_pieces = piece.Split ('=');
155 if (arg_pieces.Length != 2) {
156 throw new InvalidOperationException ("Invalid connection string");
158 string token = arg_pieces[0].ToLower (System.Globalization.CultureInfo.InvariantCulture).Trim ();
159 string tvalue = arg_pieces[1].Trim ();
160 string tvalue_lc = arg_pieces[1].ToLower (System.Globalization.CultureInfo.InvariantCulture).Trim ();
163 if (tvalue_lc.StartsWith ("file://")) {
164 db_file = tvalue.Substring (7);
165 } else if (tvalue_lc.StartsWith ("file:")) {
166 db_file = tvalue.Substring (5);
167 } else if (tvalue_lc.StartsWith ("/")) {
170 throw new InvalidOperationException ("Invalid connection string: invalid URI");
175 db_mode = Convert.ToInt32 (tvalue);
179 db_version = Convert.ToInt32 (tvalue);
182 case "encoding": // only for sqlite2
183 encoding = Encoding.GetEncoding (tvalue);
187 busy_timeout = Convert.ToInt32 (tvalue);
192 if (db_file == null) {
193 throw new InvalidOperationException ("Invalid connection string: no URI");
199 #region Internal Methods
201 internal void StartExec ()
204 state = ConnectionState.Executing;
207 internal void EndExec ()
209 state = ConnectionState.Open;
214 #region Public Methods
216 object ICloneable.Clone ()
218 return new SqliteConnection (ConnectionString);
222 public IDbTransaction BeginTransaction ()
224 if (state != ConnectionState.Open)
225 throw new InvalidOperationException("Invalid operation: The connection is closed");
227 SqliteTransaction t = new SqliteTransaction();
229 SqliteCommand cmd = (SqliteCommand)this.CreateCommand();
230 cmd.CommandText = "BEGIN";
231 cmd.ExecuteNonQuery();
235 public IDbTransaction BeginTransaction (IsolationLevel il)
237 throw new InvalidOperationException();
242 if (state != ConnectionState.Open) {
246 state = ConnectionState.Closed;
249 Sqlite.sqlite3_close (sqlite_handle);
251 Sqlite.sqlite_close (sqlite_handle);
252 sqlite_handle = IntPtr.Zero;
255 public void ChangeDatabase (string databaseName)
258 db_file = databaseName;
262 IDbCommand IDbConnection.CreateCommand ()
264 return CreateCommand ();
267 public SqliteCommand CreateCommand ()
269 return new SqliteCommand (null, this);
274 if (conn_str == null) {
275 throw new InvalidOperationException ("No database specified");
278 if (state != ConnectionState.Closed) {
282 IntPtr errmsg = IntPtr.Zero;
286 sqlite_handle = Sqlite.sqlite_open(db_file, db_mode, out errmsg);
287 if (errmsg != IntPtr.Zero) {
288 string msg = Marshal.PtrToStringAnsi (errmsg);
289 Sqlite.sqliteFree (errmsg);
290 throw new ApplicationException (msg);
292 } catch (DllNotFoundException) {
294 } catch (EntryPointNotFoundException) {
298 if (busy_timeout != 0)
299 Sqlite.sqlite_busy_timeout (sqlite_handle, busy_timeout);
302 int err = Sqlite.sqlite3_open16(db_file, out sqlite_handle);
303 if (err == (int)SqliteError.ERROR)
304 throw new ApplicationException (Marshal.PtrToStringUni( Sqlite.sqlite3_errmsg16 (sqlite_handle)));
305 if (busy_timeout != 0)
306 Sqlite.sqlite3_busy_timeout (sqlite_handle, busy_timeout);
309 state = ConnectionState.Open;