-// -*- c-basic-offset: 8; inent-tabs-mode: nil -*-
//
-// SqliteConnection.cs
+// Mono.Data.SqliteClient.SqliteConnection.cs
//
-// Author(s): Vladimir Vukicevic <vladimir@pobox.com>
+// Represents an open connection to a Sqlite database file.
//
-// Copyright (C) 2002 Vladimir Vukicevic
+// Author(s): Vladimir Vukicevic <vladimir@pobox.com>
+// Everaldo Canuto <everaldo_canuto@yahoo.com.br>
//
-
+// Copyright (C) 2002 Vladimir Vukicevic
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System;
using System.Runtime.InteropServices;
using System.Data;
+using System.Text;
namespace Mono.Data.SqliteClient
{
- public class SqliteConnection : IDbConnection
- {
- string conn_str;
- string db_file;
- int db_mode;
- IntPtr sqlite_handle;
-
- ConnectionState state;
-
- public SqliteConnection ()
- {
- db_file = null;
- db_mode = 0644;
- state = ConnectionState.Closed;
- sqlite_handle = IntPtr.Zero;
- }
-
- public SqliteConnection (string connstring)
- : this ()
- {
- ConnectionString = connstring;
- }
-
- public void Dispose ()
- {
- Close ();
- }
-
- public string ConnectionString
- {
- get {
- return conn_str;
- }
- set {
- if (value == null) {
- Close ();
- conn_str = null;
- return;
- }
-
- if (value != conn_str) {
- Close ();
- conn_str = value;
-
- db_file = null;
- db_mode = 0644;
-
- string[] conn_pieces = value.Split (',');
- foreach (string piece in conn_pieces) {
- piece.Trim ();
- string[] arg_pieces = piece.Split ('=');
- if (arg_pieces.Length != 2) {
- throw new InvalidOperationException ("Invalid connection string");
- }
- string token = arg_pieces[0].ToLower ();
- string tvalue = arg_pieces[1];
- string tvalue_lc = arg_pieces[1].ToLower ();
- if (token == "uri") {
- if (tvalue_lc.StartsWith ("file://")) {
- db_file = tvalue.Substring (6);
- } else if (tvalue_lc.StartsWith ("file:")) {
- db_file = tvalue.Substring (5);
- } else if (tvalue_lc.StartsWith ("/")) {
- db_file = tvalue;
- } else {
- throw new InvalidOperationException ("Invalid connection string: invalid URI");
- }
- } else if (token == "mode") {
- db_mode = Convert.ToInt32 (tvalue);
- }
- }
-
- if (db_file == null) {
- throw new InvalidOperationException ("Invalid connection string: no URI");
- }
- }
- }
- }
-
- public int ConnectionTimeout
- {
- get {
- return 0;
- }
- }
-
- public string Database
- {
- get {
- return db_file;
- }
- }
-
- public ConnectionState State
- {
- get {
- return state;
- }
- }
-
- internal IntPtr Handle
- {
- get {
- return sqlite_handle;
- }
- }
-
- public void Open ()
- {
- if (conn_str == null) {
- throw new InvalidOperationException ("No database specified");
- }
-
- if (state != ConnectionState.Closed) {
- return;
- }
-
- string errmsg;
- sqlite_handle = sqlite_open (db_file, db_mode, out errmsg);
-
- if (errmsg != null) {
- throw new ApplicationException (errmsg);
- }
-
- state = ConnectionState.Open;
- }
-
- public void Close ()
- {
- if (state != ConnectionState.Open) {
- return;
- }
-
- state = ConnectionState.Closed;
-
- sqlite_close (sqlite_handle);
- sqlite_handle = IntPtr.Zero;
- }
+ public class SqliteConnection : IDbConnection
+ {
+
+ #region Fields
+
+ private string conn_str;
+ private string db_file;
+ private int db_mode;
+ private int db_version;
+ private IntPtr sqlite_handle;
+ private ConnectionState state;
+ private Encoding encoding;
+ private int busy_timeout;
+
+ #endregion
+
+ #region Constructors and destructors
+
+ public SqliteConnection ()
+ {
+ db_file = null;
+ db_mode = 0644;
+ db_version = 2;
+ state = ConnectionState.Closed;
+ sqlite_handle = IntPtr.Zero;
+ encoding = null;
+ busy_timeout = 0;
+ }
+
+ public SqliteConnection (string connstring) : this ()
+ {
+ ConnectionString = connstring;
+ }
+
+ public void Dispose ()
+ {
+ Close ();
+ }
+
+ #endregion
+
+ #region Properties
+
+ public string ConnectionString {
+ get { return conn_str; }
+ set { SetConnectionString(value); }
+ }
+
+ public int ConnectionTimeout {
+ get { return 0; }
+ }
+
+ public string Database {
+ get { return db_file; }
+ }
+
+ public ConnectionState State {
+ get { return state; }
+ }
+
+ public Encoding Encoding {
+ get { return encoding; }
+ }
+
+ public int Version {
+ get { return db_version; }
+ }
+ internal IntPtr Handle {
+ get { return sqlite_handle; }
+ }
+
public int LastInsertRowId {
get {
- return sqlite_last_insert_rowid (Handle);
+ if (Version == 3)
+ return (int)Sqlite.sqlite3_last_insert_rowid (Handle);
+ else
+ return Sqlite.sqlite_last_insert_rowid (Handle);
}
}
- public void ChangeDatabase (string databaseName)
- {
- throw new NotImplementedException ();
- }
-
- IDbCommand IDbConnection.CreateCommand ()
- {
- return CreateCommand ();
- }
+ public int BusyTimeout {
+ get {
+ return busy_timeout;
+ }
+ set {
+ busy_timeout = value < 0 ? 0 : value;
+ }
+ }
+
+ #endregion
- public SqliteCommand CreateCommand ()
- {
- return new SqliteCommand (null, this);
- }
+ #region Private Methods
+
+ private void SetConnectionString(string connstring)
+ {
+ if (connstring == null) {
+ Close ();
+ conn_str = null;
+ return;
+ }
+
+ if (connstring != conn_str) {
+ Close ();
+ conn_str = connstring;
+
+ db_file = null;
+ db_mode = 0644;
+
+ string[] conn_pieces = connstring.Split (',');
+ for (int i = 0; i < conn_pieces.Length; i++) {
+ string piece = conn_pieces [i].Trim ();
+ if (piece.Length == 0) { // ignore empty elements
+ continue;
+ }
+ string[] arg_pieces = piece.Split ('=');
+ if (arg_pieces.Length != 2) {
+ throw new InvalidOperationException ("Invalid connection string");
+ }
+ string token = arg_pieces[0].ToLower (System.Globalization.CultureInfo.InvariantCulture).Trim ();
+ string tvalue = arg_pieces[1].Trim ();
+ string tvalue_lc = arg_pieces[1].ToLower (System.Globalization.CultureInfo.InvariantCulture).Trim ();
+ switch (token) {
+ case "uri":
+ if (tvalue_lc.StartsWith ("file://")) {
+ db_file = tvalue.Substring (7);
+ } else if (tvalue_lc.StartsWith ("file:")) {
+ db_file = tvalue.Substring (5);
+ } else if (tvalue_lc.StartsWith ("/")) {
+ db_file = tvalue;
+ } else {
+ throw new InvalidOperationException ("Invalid connection string: invalid URI");
+ }
+ break;
+
+ case "mode":
+ db_mode = Convert.ToInt32 (tvalue);
+ break;
+
+ case "version":
+ db_version = Convert.ToInt32 (tvalue);
+ break;
+
+ case "encoding": // only for sqlite2
+ encoding = Encoding.GetEncoding (tvalue);
+ break;
+
+ case "busy_timeout":
+ busy_timeout = Convert.ToInt32 (tvalue);
+ break;
+ }
+ }
+
+ if (db_file == null) {
+ throw new InvalidOperationException ("Invalid connection string: no URI");
+ }
+ }
+ }
+
+ #endregion
- public IDbTransaction BeginTransaction ()
+ #region Internal Methods
+
+ internal void StartExec ()
+ {
+ // use a mutex here
+ state = ConnectionState.Executing;
+ }
+
+ internal void EndExec ()
{
- if (state != ConnectionState.Open)
- throw new InvalidOperationException("Invalid operation: The connection is close");
+ state = ConnectionState.Open;
+ }
+
+ #endregion
+ #region Public Methods
+
+ public IDbTransaction BeginTransaction ()
+ {
+ if (state != ConnectionState.Open)
+ throw new InvalidOperationException("Invalid operation: The connection is closed");
+
SqliteTransaction t = new SqliteTransaction();
t.Connection = this;
SqliteCommand cmd = this.CreateCommand();
cmd.CommandText = "BEGIN";
cmd.ExecuteNonQuery();
return t;
- }
-
- public IDbTransaction BeginTransaction (IsolationLevel il)
- {
- return null;
- }
-
- internal void StartExec ()
- {
- // use a mutex here
- state = ConnectionState.Executing;
- }
-
- internal void EndExec ()
- {
- state = ConnectionState.Open;
- }
-
- [DllImport("sqlite")]
- static extern IntPtr sqlite_open (string dbname, int db_mode, out string errstr);
-
- [DllImport("sqlite")]
- static extern void sqlite_close (IntPtr sqlite_handle);
+ }
+
+ public IDbTransaction BeginTransaction (IsolationLevel il)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public void Close ()
+ {
+ if (state != ConnectionState.Open) {
+ return;
+ }
+
+ state = ConnectionState.Closed;
+
+ if (Version == 3)
+ Sqlite.sqlite3_close (sqlite_handle);
+ else
+ Sqlite.sqlite_close(sqlite_handle);
+ sqlite_handle = IntPtr.Zero;
+ }
+
+ public void ChangeDatabase (string databaseName)
+ {
+ throw new NotImplementedException ();
+ }
+
+ IDbCommand IDbConnection.CreateCommand ()
+ {
+ return CreateCommand ();
+ }
+
+ public SqliteCommand CreateCommand ()
+ {
+ return new SqliteCommand (null, this);
+ }
+
+ public void Open ()
+ {
+ if (conn_str == null) {
+ throw new InvalidOperationException ("No database specified");
+ }
+
+ if (state != ConnectionState.Closed) {
+ return;
+ }
+
+ IntPtr errmsg = IntPtr.Zero;
+
+ if (Version == 2){
+ try {
+ sqlite_handle = Sqlite.sqlite_open(db_file, db_mode, out errmsg);
+ if (errmsg != IntPtr.Zero) {
+ string msg = Marshal.PtrToStringAnsi (errmsg);
+ Sqlite.sqliteFree (errmsg);
+ throw new ApplicationException (msg);
+ }
+ } catch (DllNotFoundException dll) {
+ db_version = 3;
+ }
+ if (busy_timeout != 0)
+ Sqlite.sqlite_busy_timeout (sqlite_handle, busy_timeout);
+ }
+ if (Version == 3) {
+ int err = Sqlite.sqlite3_open16(db_file, out sqlite_handle);
+ if (err == (int)SqliteError.ERROR)
+ throw new ApplicationException (Marshal.PtrToStringUni( Sqlite.sqlite3_errmsg16 (sqlite_handle)));
+ if (busy_timeout != 0)
+ Sqlite.sqlite3_busy_timeout (sqlite_handle, busy_timeout);
+ } else {
+ }
+ state = ConnectionState.Open;
+ }
+
+ #endregion
- [DllImport("sqlite")]
- static extern int sqlite_last_insert_rowid (IntPtr sqlite_handle);
- }
+ }
}