+2006-01-02 Joshua Tauberer <tauberer@for.net
+
+ * Added Mono.Data.SqliteClient/SqliteExceptions.cs to
+ the sources files.
+
2005-10-06 Chris Lahey <clahey@localhost.localdomain>
* Makefile (LIB_MCS_FLAGS): Requires Mono.Posix.dll.
Mono.Data.SqliteClient/SqliteRowUpdatingEventArgs.cs
Mono.Data.SqliteClient/SqliteRowUpdatingEventHandler.cs
Mono.Data.SqliteClient/SqliteTransaction.cs
+Mono.Data.SqliteClient/SqliteExceptions.cs
+2006-01-02 Joshua Tauberer <tauberer@for.net>
+
+ * SqliteCommand.cs: It was revealed that preparing
+ statements ahead of time was not possible as table
+ schema changes lead to errors. This needed serious
+ reorganization. SQL syntax errors and BUSY errors
+ are now raised in nice exceptions.
+ * SqliteDataReader.cs:
+ * Use object[] in place of ArrayList for each row.
+ * For Sqlite3, which remembers whether a value was
+ an integer, text, real, or blob, actually return
+ longs, strings, doubles, and byte[]s.
+ * GetDataTypeName() works where possible (Sqlite3).
+ * INT/INTEGER columns are now returned as ints,
+ rather than longs, for Sqlite3. Similarly for
+ DATE and DATETIME columns, now returning DateTimes.
+ * SqliteConnection.cs.cs: BeginTransaction(IsolationLevel)
+ throws InvalidOperationException per the MS docs.
+ * SqliteExceptions.cs: New file with SqliteSyntaxException,
+ SqliteExecutionException, and its subclass SqliteBusyException.
+
2005-12-27 Jonathan Pryor <jonpryor@vt.edu>
* SqliteCommand.cs: Use non-obsolete UnixMarshal members.
[DllImport ("sqlite3")]
internal static extern double sqlite3_column_double (IntPtr pVm, int col);
+ [DllImport ("sqlite3")]
+ internal static extern IntPtr sqlite3_column_decltype (IntPtr pVm, int col);
+
[DllImport ("sqlite3")]
internal static extern int sqlite3_bind_parameter_count (IntPtr pStmt);
// Chris Turchin <chris@turchin.net>
// Jeroen Zwartepoorte <jeroen@xs4all.nl>
// Thomas Zoechling <thomas.zoechling@gmx.at>
+// Joshua Tauberer <tauberer@for.net>
//
// Copyright (C) 2002 Vladimir Vukicevic
//
private UpdateRowSource upd_row_source;
private SqliteParameterCollection sql_params;
private bool prepared = false;
- private ArrayList pStmts;
+
+ static Regex v2Parameters = new Regex(@"(('[^']*?\:[^']*')*[^':]*?)*(?<param>:\w+)+([^':]*?('[^']*?\:[^']*'))*", RegexOptions.ExplicitCapture);
#endregion
return m.Value;
}
+ private void BindParameters3 (IntPtr pStmt)
+ {
+ if (sql_params == null) return;
+ if (sql_params.Count == 0) return;
+
+ int pcount = Sqlite.sqlite3_bind_parameter_count (pStmt);
+
+ for (int i = 1; i <= pcount; i++)
+ {
+ String name = Sqlite.sqlite3_bind_parameter_name (pStmt, i);
+ SqliteParameter param = sql_params[name];
+ Type ptype = param.Value.GetType ();
+
+ SqliteError err;
+
+ if (ptype.Equals (typeof (String)))
+ {
+ String s = (String)param.Value;
+ err = Sqlite.sqlite3_bind_text (pStmt, i, s, s.Length, (IntPtr)(-1));
+ }
+ else if (ptype.Equals (typeof (DBNull)))
+ {
+ err = Sqlite.sqlite3_bind_null (pStmt, i);
+ }
+ else if (ptype.Equals (typeof (Boolean)))
+ {
+ bool b = (bool)param.Value;
+ err = Sqlite.sqlite3_bind_int (pStmt, i, b ? 1 : 0);
+ } else if (ptype.Equals (typeof (Byte)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (Byte)param.Value);
+ }
+ else if (ptype.Equals (typeof (Char)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (Char)param.Value);
+ }
+ else if (ptype.Equals (typeof (Int16)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (Int16)param.Value);
+ }
+ else if (ptype.Equals (typeof (Int32)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (Int32)param.Value);
+ }
+ else if (ptype.Equals (typeof (SByte)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (SByte)param.Value);
+ }
+ else if (ptype.Equals (typeof (UInt16)))
+ {
+ err = Sqlite.sqlite3_bind_int (pStmt, i, (UInt16)param.Value);
+ }
+ else if (ptype.Equals (typeof (DateTime)))
+ {
+ DateTime dt = (DateTime)param.Value;
+ err = Sqlite.sqlite3_bind_int64 (pStmt, i, dt.ToFileTime ());
+ }
+ else if (ptype.Equals (typeof (Double)))
+ {
+ err = Sqlite.sqlite3_bind_double (pStmt, i, (Double)param.Value);
+ }
+ else if (ptype.Equals (typeof (Single)))
+ {
+ err = Sqlite.sqlite3_bind_double (pStmt, i, (Single)param.Value);
+ }
+ else if (ptype.Equals (typeof (UInt32)))
+ {
+ err = Sqlite.sqlite3_bind_int64 (pStmt, i, (UInt32)param.Value);
+ }
+ else if (ptype.Equals (typeof (Int64)))
+ {
+ err = Sqlite.sqlite3_bind_int64 (pStmt, i, (Int64)param.Value);
+ }
+ else
+ {
+ throw new ApplicationException("Unkown Parameter Type");
+ }
+ if (err != SqliteError.OK)
+ {
+ throw new ApplicationException ("Sqlite error in bind " + err);
+ }
+ }
+ }
+
+ private void GetNextStatement (IntPtr pzStart, out IntPtr pzTail, out IntPtr pStmt)
+ {
+ if (parent_conn.Version == 3)
+ {
+ SqliteError err = Sqlite.sqlite3_prepare (parent_conn.Handle, pzStart, -1, out pStmt, out pzTail);
+ if (err != SqliteError.OK)
+ throw new SqliteSyntaxException (GetError3());
+ }
+ else
+ {
+ IntPtr errMsg;
+ SqliteError err = Sqlite.sqlite_compile (parent_conn.Handle, pzStart, out pzTail, out pStmt, out errMsg);
+
+ if (err != SqliteError.OK)
+ {
+ string msg = "unknown error";
+ if (errMsg != IntPtr.Zero)
+ {
+ msg = Marshal.PtrToStringAnsi (errMsg);
+ Sqlite.sqliteFree (errMsg);
+ }
+ throw new SqliteSyntaxException (msg);
+ }
+ }
+ }
+
+ // Executes a statement and ignores its result.
+ private void ExecuteStatement (IntPtr pStmt) {
+ int cols;
+ IntPtr pazValue, pazColName;
+ ExecuteStatement (pStmt, out cols, out pazValue, out pazColName);
+ }
+
+ // Executes a statement and returns whether there is more data available.
+ internal bool ExecuteStatement (IntPtr pStmt, out int cols, out IntPtr pazValue, out IntPtr pazColName) {
+ SqliteError err;
+
+ if (parent_conn.Version == 3)
+ {
+ err = Sqlite.sqlite3_step (pStmt);
+ if (err == SqliteError.ERROR)
+ throw new SqliteExecutionException (GetError3());
+ pazValue = IntPtr.Zero; pazColName = IntPtr.Zero; // not used for v=3
+ cols = Sqlite.sqlite3_column_count (pStmt);
+ }
+ else
+ {
+ err = Sqlite.sqlite_step (pStmt, out cols, out pazValue, out pazColName);
+ if (err == SqliteError.ERROR)
+ throw new SqliteExecutionException ();
+ }
+
+ if (err == SqliteError.BUSY)
+ throw new SqliteBusyException();
+
+ if (err == SqliteError.MISUSE)
+ throw new SqliteExecutionException();
+
+ // err is either ROW or DONE.
+ return err == SqliteError.ROW;
+ }
+
#endregion
#region Public Methods
//The above statement is true for the commented regEx, but I changed it to use the :-prefix, because now (12.05.2005 sqlite3)
//sqlite is using : as Standard Parameterprefix
- Regex r = new Regex(@"(('[^']*?\:[^']*')*[^':]*?)*(?<param>:\w+)+([^':]*?('[^']*?\:[^']*'))*",RegexOptions.ExplicitCapture);
MatchEvaluator me = new MatchEvaluator(ReplaceParams);
- processedText = r.Replace(sql, me);
+ processedText = v2Parameters.Replace(sql, me);
return processedText;
}
public void Prepare ()
{
- pStmts = new ArrayList();
- string sqlcmds = sql;
+ // There isn't much we can do here. If a table schema
+ // changes after preparing a statement, Sqlite bails,
+ // so we can only compile statements right before we
+ // want to run them.
+ if (prepared) return;
+
if (Parameters.Count > 0 && parent_conn.Version == 2)
{
- sqlcmds = ProcessParameters();
+ sql = ProcessParameters();
}
- SqliteError err = SqliteError.OK;
- IntPtr psql = UnixMarshal.StringToHeap(sqlcmds);
- IntPtr pzTail = psql;
- try {
- do { // sql may contain multiple sql commands, loop until they're all processed
- IntPtr pStmt = IntPtr.Zero;
- if (parent_conn.Version == 3)
- {
- err = Sqlite.sqlite3_prepare (parent_conn.Handle, pzTail, sql.Length, out pStmt, out pzTail);
- if (err != SqliteError.OK) {
- string msg = Marshal.PtrToStringAnsi (Sqlite.sqlite3_errmsg (parent_conn.Handle));
- throw new ApplicationException (msg);
- }
- }
- else
- {
- IntPtr errMsg;
- err = Sqlite.sqlite_compile (parent_conn.Handle, pzTail, out pzTail, out pStmt, out errMsg);
-
- if (err != SqliteError.OK)
- {
- string msg = "unknown error";
- if (errMsg != IntPtr.Zero)
- {
- msg = Marshal.PtrToStringAnsi (errMsg);
- Sqlite.sqliteFree (errMsg);
- }
- throw new ApplicationException ("Sqlite error: " + msg);
- }
- }
-
- pStmts.Add(pStmt);
-
- if (parent_conn.Version == 3)
- {
- int pcount = Sqlite.sqlite3_bind_parameter_count (pStmt);
- if (sql_params == null) pcount = 0;
-
- for (int i = 1; i <= pcount; i++)
- {
- String name = Sqlite.sqlite3_bind_parameter_name (pStmt, i);
- SqliteParameter param = sql_params[name];
- Type ptype = param.Value.GetType ();
-
- if (ptype.Equals (typeof (String)))
- {
- String s = (String)param.Value;
- err = Sqlite.sqlite3_bind_text (pStmt, i, s, s.Length, (IntPtr)(-1));
- }
- else if (ptype.Equals (typeof (DBNull)))
- {
- err = Sqlite.sqlite3_bind_null (pStmt, i);
- }
- else if (ptype.Equals (typeof (Boolean)))
- {
- bool b = (bool)param.Value;
- err = Sqlite.sqlite3_bind_int (pStmt, i, b ? 1 : 0);
- } else if (ptype.Equals (typeof (Byte)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (Byte)param.Value);
- }
- else if (ptype.Equals (typeof (Char)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (Char)param.Value);
- }
- else if (ptype.Equals (typeof (Int16)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (Int16)param.Value);
- }
- else if (ptype.Equals (typeof (Int32)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (Int32)param.Value);
- }
- else if (ptype.Equals (typeof (SByte)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (SByte)param.Value);
- }
- else if (ptype.Equals (typeof (UInt16)))
- {
- err = Sqlite.sqlite3_bind_int (pStmt, i, (UInt16)param.Value);
- }
- else if (ptype.Equals (typeof (DateTime)))
- {
- DateTime dt = (DateTime)param.Value;
- err = Sqlite.sqlite3_bind_int64 (pStmt, i, dt.ToFileTime ());
- }
- else if (ptype.Equals (typeof (Double)))
- {
- err = Sqlite.sqlite3_bind_double (pStmt, i, (Double)param.Value);
- }
- else if (ptype.Equals (typeof (Single)))
- {
- err = Sqlite.sqlite3_bind_double (pStmt, i, (Single)param.Value);
- }
- else if (ptype.Equals (typeof (UInt32)))
- {
- err = Sqlite.sqlite3_bind_int64 (pStmt, i, (UInt32)param.Value);
- }
- else if (ptype.Equals (typeof (Int64)))
- {
- err = Sqlite.sqlite3_bind_int64 (pStmt, i, (Int64)param.Value);
- }
- else
- {
- throw new ApplicationException("Unkown Parameter Type");
- }
- if (err != SqliteError.OK)
- {
- throw new ApplicationException ("Sqlite error in bind " + err);
- }
- }
- }
- } while ((int)pzTail - (int)psql < sql.Length);
- } finally {
- UnixMarshal.FreeHeap(psql);
- }
- prepared=true;
+ prepared = true;
}
-
IDbDataParameter IDbCommand.CreateParameter()
{
return CreateParameter ();
public int ExecuteNonQuery ()
{
int rows_affected;
- SqliteDataReader r = ExecuteReader (CommandBehavior.Default, false, out rows_affected);
+ ExecuteReader (CommandBehavior.Default, false, out rows_affected);
return rows_affected;
}
public SqliteDataReader ExecuteReader (CommandBehavior behavior, bool want_results, out int rows_affected)
{
- SqliteDataReader reader = null;
- SqliteError err = SqliteError.OK;
- IntPtr errMsg = IntPtr.Zero;
+ // The SQL string may contain multiple sql commands, so the main
+ // thing to do is have Sqlite iterate through the commands.
+ // If want_results, only the last command is returned as a
+ // DataReader. Otherwise, no command is returned as a
+ // DataReader.
+
+ IntPtr psql = UnixMarshal.StringToHeap(sql);
+ IntPtr pzTail = psql;
+ IntPtr errMsgPtr;
+
parent_conn.StartExec ();
-
- try
- {
- if (!prepared)
- {
- Prepare ();
- }
- for (int i = 0; i < pStmts.Count; i++) {
- IntPtr pStmt = (IntPtr)pStmts[i];
+
+ rows_affected = 0;
+
+ try {
+ while (true) {
+ IntPtr pStmt;
+
+ GetNextStatement(pzTail, out pzTail, out pStmt);
- // If want_results, return the results of the last statement
- // via the SqliteDataReader, and execute but ignore the results
- // of the other statements.
- if (i == pStmts.Count-1 && want_results)
- {
- reader = new SqliteDataReader (this, pStmt, parent_conn.Version);
- break;
- }
+ if (pStmt == IntPtr.Zero)
+ throw new Exception();
- // Execute but ignore the results of these statements.
- if (parent_conn.Version == 3)
- {
- err = Sqlite.sqlite3_step (pStmt);
- }
- else
- {
- int cols;
- IntPtr pazValue = IntPtr.Zero;
- IntPtr pazColName = IntPtr.Zero;
- err = Sqlite.sqlite_step (pStmt, out cols, out pazValue, out pazColName);
- }
- // On error, misuse, or busy, don't bother with the rest of the statements.
- if (err != SqliteError.ROW && err != SqliteError.DONE) break;
- }
- }
- finally
- {
- foreach (IntPtr pStmt in pStmts) {
- if (parent_conn.Version == 3)
- {
- err = Sqlite.sqlite3_finalize (pStmt);
- }
- else
- {
- err = Sqlite.sqlite_finalize (pStmt, out errMsg);
+ // pzTail is positioned after the last byte in the
+ // statement, which will be the NULL character if
+ // this was the last statement.
+ bool last = Marshal.ReadByte(pzTail) == 0;
+
+ try {
+ if (parent_conn.Version == 3)
+ BindParameters3 (pStmt);
+
+ if (last && want_results)
+ return new SqliteDataReader (this, pStmt, parent_conn.Version);
+
+ ExecuteStatement(pStmt);
+
+ if (last) // rows_affected is only used if !want_results
+ rows_affected = NumChanges ();
+
+ } finally {
+ if (parent_conn.Version == 3)
+ Sqlite.sqlite3_finalize (pStmt);
+ else
+ Sqlite.sqlite_finalize (pStmt, out errMsgPtr);
}
+
+ if (last) break;
}
+
+ return null;
+ } finally {
parent_conn.EndExec ();
- prepared = false;
- }
-
- if (err != SqliteError.OK &&
- err != SqliteError.DONE &&
- err != SqliteError.ROW)
- {
- if (errMsg != IntPtr.Zero)
- {
- // TODO: Get the message text
- }
- throw new ApplicationException ("Sqlite error");
+ UnixMarshal.FreeHeap (psql);
}
- rows_affected = NumChanges ();
- return reader;
}
-
+
public int LastInsertRowID ()
{
if (parent_conn.Version == 3)
else
return Sqlite.sqlite_last_insert_rowid(parent_conn.Handle);
}
+
+ private string GetError3() {
+ return Marshal.PtrToStringAnsi (Sqlite.sqlite3_errmsg (parent_conn.Handle));
+ }
#endregion
}
}
public IDbTransaction BeginTransaction ()
{
if (state != ConnectionState.Open)
- throw new InvalidOperationException("Invalid operation: The connection is close");
+ throw new InvalidOperationException("Invalid operation: The connection is closed");
SqliteTransaction t = new SqliteTransaction();
t.Connection = this;
public IDbTransaction BeginTransaction (IsolationLevel il)
{
- return null;
+ throw new InvalidOperationException();
}
public void Close ()
}
IntPtr errmsg = IntPtr.Zero;
- Exception dll_error = null;
if (Version == 2){
try {
Sqlite.sqliteFree (errmsg);
throw new ApplicationException (msg);
}
- } catch (DllNotFoundException dll){
- dll_error = dll;
+ } catch (DllNotFoundException dll) {
db_version = 3;
}
}
//
// Author(s): Vladimir Vukicevic <vladimir@pobox.com>
// Everaldo Canuto <everaldo_canuto@yahoo.com.br>
+// Joshua Tauberer <tauberer@for.net>
//
// Copyright (C) 2002 Vladimir Vukicevic
//
private SqliteCommand command;
private ArrayList rows;
- private ArrayList columns;
+ private string[] columns;
private Hashtable column_names;
private int current_row;
private bool closed;
private bool reading;
private int records_affected;
+ private string[] decltypes;
#endregion
{
command = cmd;
rows = new ArrayList ();
- columns = new ArrayList ();
column_names = new Hashtable ();
closed = false;
current_row = -1;
reading = true;
- ReadpVm (pVm, version);
+ ReadpVm (pVm, version, cmd);
ReadingDone ();
}
}
public int FieldCount {
- get { return columns.Count; }
+ get { return columns.Length; }
}
public object this[string name] {
- get { return ((ArrayList) rows[current_row])[(int) column_names[name]]; }
+ get { return ((object[]) rows[current_row])[(int) column_names[name]]; }
}
public object this[int i] {
- get { return ((ArrayList) rows[current_row])[i]; }
+ get { return ((object[]) rows[current_row])[i]; }
}
public bool IsClosed {
#region Internal Methods
- internal void ReadpVm (IntPtr pVm, int version)
+ internal void ReadpVm (IntPtr pVm, int version, SqliteCommand cmd)
{
- int pN = 0;
- IntPtr pazValue = IntPtr.Zero;
- IntPtr pazColName = IntPtr.Zero;
- SqliteError res;
+ int pN;
+ IntPtr pazValue;
+ IntPtr pazColName;
+ bool first = true;
+
+ int[] declmode = null;
while (true) {
- if (version == 3) {
- res = Sqlite.sqlite3_step (pVm);
- pN = Sqlite.sqlite3_column_count (pVm);
- } else
- res = Sqlite.sqlite_step (pVm, out pN, out pazValue, out pazColName);
- if (res == SqliteError.ERROR) {
- throw new ApplicationException ("Sqlite error");
- }
- if (res == SqliteError.DONE) {
- break;
- }
- // We have some data; lets read it
- if (column_names.Count == 0) {
+ bool hasdata = cmd.ExecuteStatement(pVm, out pN, out pazValue, out pazColName);
+
+ // For the first row, get the column information
+ if (first) {
+ first = false;
+
+ if (version == 3) {
+ // A decltype might be null if the type is unknown to sqlite.
+ decltypes = new string[pN];
+ declmode = new int[pN]; // 1 == integer, 2 == datetime
+ for (int i = 0; i < pN; i++) {
+ IntPtr decl = Sqlite.sqlite3_column_decltype (pVm, i);
+ if (decl != IntPtr.Zero) {
+ decltypes[i] = Marshal.PtrToStringAnsi (decl).ToLower();
+ if (decltypes[i] == "int" || decltypes[i] == "integer")
+ declmode[i] = 1;
+ else if (decltypes[i] == "date" || decltypes[i] == "datetime")
+ declmode[i] = 2;
+ }
+ }
+ }
+
+ columns = new string[pN];
for (int i = 0; i < pN; i++) {
- string colName = "";
+ string colName;
if (version == 2) {
IntPtr fieldPtr = (IntPtr)Marshal.ReadInt32 (pazColName, i*IntPtr.Size);
colName = Marshal.PtrToStringAnsi (fieldPtr);
} else {
colName = Marshal.PtrToStringAnsi (Sqlite.sqlite3_column_name (pVm, i));
}
- columns.Add (colName);
+ columns[i] = colName;
column_names [colName] = i;
}
}
- ArrayList data_row = new ArrayList (pN);
+
+ if (!hasdata) break;
+
+ object[] data_row = new object [pN];
for (int i = 0; i < pN; i++) {
- string colData = "";
if (version == 2) {
IntPtr fieldPtr = (IntPtr)Marshal.ReadInt32 (pazValue, i*IntPtr.Size);
- colData = Marshal.PtrToStringAnsi (fieldPtr);
- data_row.Add (Marshal.PtrToStringAnsi (fieldPtr));
+ data_row[i] = Marshal.PtrToStringAnsi (fieldPtr);
} else {
switch (Sqlite.sqlite3_column_type (pVm, i)) {
case 1:
- Int64 sqliteint64 = Sqlite.sqlite3_column_int64 (pVm, i);
- data_row.Add (sqliteint64.ToString ());
+ // If the column was declared as an 'int' or 'integer', let's play
+ // nice and return an int (version 3 only).
+ if (declmode[i] == 1)
+ data_row[i] = (int)Sqlite.sqlite3_column_int64 (pVm, i);
+ else
+ data_row[i] = Sqlite.sqlite3_column_int64 (pVm, i);
break;
case 2:
- double sqlitedouble = Sqlite.sqlite3_column_double (pVm, i);
- data_row.Add (sqlitedouble.ToString ());
+ data_row[i] = Sqlite.sqlite3_column_double (pVm, i);
break;
case 3:
- colData = Marshal.PtrToStringAnsi (Sqlite.sqlite3_column_text (pVm, i));
- data_row.Add (colData);
+ data_row[i] = Marshal.PtrToStringAnsi (Sqlite.sqlite3_column_text (pVm, i));
+
+ // If the column was declared as a 'date' or 'datetime', let's play
+ // nice and return a DateTime (version 3 only).
+ if (declmode[i] == 2)
+ data_row[i] = DateTime.Parse((string)data_row[i]);
break;
case 4:
int blobbytes = Sqlite.sqlite3_column_bytes (pVm, i);
IntPtr blobptr = Sqlite.sqlite3_column_blob (pVm, i);
byte[] blob = new byte[blobbytes];
Marshal.Copy (blobptr, blob, 0, blobbytes);
- data_row.Add (blob);
+ data_row[i] = blob;
break;
case 5:
- data_row.Add (null);
+ data_row[i] = null;
break;
default:
throw new ApplicationException ("FATAL: Unknown sqlite3_column_type");
}
- }
+ }
}
+
rows.Add (data_row);
}
}
public bool GetBoolean (int i)
{
- return Convert.ToBoolean ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToBoolean (((object[]) rows[current_row])[i]);
}
public byte GetByte (int i)
{
- return Convert.ToByte ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToByte (((object[]) rows[current_row])[i]);
}
public long GetBytes (int i, long fieldOffset, byte[] buffer, int bufferOffset, int length)
public char GetChar (int i)
{
- return Convert.ToChar ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToChar (((object[]) rows[current_row])[i]);
}
public long GetChars (int i, long fieldOffset, char[] buffer, int bufferOffset, int length)
public string GetDataTypeName (int i)
{
+ if (decltypes != null && decltypes[i] != null)
+ return decltypes[i];
return "text"; // SQL Lite data type
}
public DateTime GetDateTime (int i)
{
- return Convert.ToDateTime ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToDateTime (((object[]) rows[current_row])[i]);
}
public decimal GetDecimal (int i)
{
- return Convert.ToDecimal ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToDecimal (((object[]) rows[current_row])[i]);
}
public double GetDouble (int i)
{
- return Convert.ToDouble ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToDouble (((object[]) rows[current_row])[i]);
}
public Type GetFieldType (int i)
{
- return System.Type.GetType ("System.String"); // .NET data type
+ return ((object[]) rows[current_row])[i].GetType();
}
public float GetFloat (int i)
{
- return Convert.ToSingle ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToSingle (((object[]) rows[current_row])[i]);
}
public Guid GetGuid (int i)
public short GetInt16 (int i)
{
- return Convert.ToInt16 ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToInt16 (((object[]) rows[current_row])[i]);
}
public int GetInt32 (int i)
{
- return Convert.ToInt32 ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToInt32 (((object[]) rows[current_row])[i]);
}
public long GetInt64 (int i)
{
- return Convert.ToInt64 ((string) ((ArrayList) rows[current_row])[i]);
+ return Convert.ToInt64 (((object[]) rows[current_row])[i]);
}
public string GetName (int i)
{
- return (string) columns[i];
+ return columns[i];
}
public int GetOrdinal (string name)
public string GetString (int i)
{
- return ((string) ((ArrayList) rows[current_row])[i]);
+ return (((object[]) rows[current_row])[i]).ToString();
}
public object GetValue (int i)
{
- return ((ArrayList) rows[current_row])[i];
+ return ((object[]) rows[current_row])[i];
}
public int GetValues (object[] values)
{
- int num_to_fill = System.Math.Min (values.Length, columns.Count);
+ int num_to_fill = System.Math.Min (values.Length, columns.Length);
for (int i = 0; i < num_to_fill; i++) {
- if (((ArrayList) rows[current_row])[i] != null) {
- values[i] = ((ArrayList) rows[current_row])[i];
+ if (((object[]) rows[current_row])[i] != null) {
+ values[i] = ((object[]) rows[current_row])[i];
} else {
values[i] = DBNull.Value;
}
public bool IsDBNull (int i)
{
- return (((ArrayList) rows[current_row])[i] == null);
+ return (((object[]) rows[current_row])[i] == null);
}
#endregion
--- /dev/null
+using System;
+using System.Data;
+
+namespace Mono.Data.SqliteClient
+{
+ // This exception is raised whenever a statement cannot be compiled.
+ public class SqliteSyntaxException : ApplicationException
+ {
+ public SqliteSyntaxException() : this("An error occurred compiling the Sqlite command.")
+ {
+ }
+
+ public SqliteSyntaxException(string message) : base(message)
+ {
+ }
+
+ public SqliteSyntaxException(string message, Exception cause) : base(message, cause)
+ {
+ }
+ }
+
+ // This exception is raised whenever the execution
+ // of a statement fails.
+ public class SqliteExecutionException : ApplicationException
+ {
+ public SqliteExecutionException() : this("An error occurred executing the Sqlite command.")
+ {
+ }
+
+ public SqliteExecutionException(string message) : base(message)
+ {
+ }
+
+ public SqliteExecutionException(string message, Exception cause) : base(message, cause)
+ {
+ }
+ }
+
+ // This exception is raised whenever Sqlite says it
+ // cannot run a command because something is busy.
+ public class SqliteBusyException : SqliteExecutionException
+ {
+ public SqliteBusyException() : this("The database is locked.")
+ {
+ }
+
+ public SqliteBusyException(string message) : base(message)
+ {
+ }
+
+ public SqliteBusyException(string message, Exception cause) : base(message, cause)
+ {
+ }
+ }
+
+}
\ No newline at end of file
+2006-01-02 Joshua Tauberer <tauberer@for.net>
+
+ * SqliteTest.cs: Cleaned up and added new stuff.
+
2005-05-20 Sureshkumar T <tsureshkumar@novell.com>
* test.sql: script to create a test db.
[STAThread]\r
static void Main(string[] args)\r
{\r
- Console.WriteLine("If this test works, you should get:");\r
- Console.WriteLine("Data 1: 5");\r
- Console.WriteLine("Data 2: Mono");\r
-\r
- Console.WriteLine("create SqliteConnection...");\r
+ Test(false);\r
+ Console.WriteLine();\r
+ Test(true);\r
+ }\r
+ \r
+ static void Test(bool v3) {\r
+ if (!v3)\r
+ Console.WriteLine("Testing Version 2");\r
+ else\r
+ Console.WriteLine("Testing Version 3");\r
+ \r
+ System.IO.File.Delete("SqliteTest.db");\r
+ \r
SqliteConnection dbcon = new SqliteConnection();\r
\r
// the connection string is a URL that points\r
// "URI=file:some/path"\r
string connectionString =\r
"URI=file:SqliteTest.db";\r
- Console.WriteLine("setting ConnectionString using: " + \r
- connectionString);\r
+ if (v3)\r
+ connectionString += ",Version=3";\r
dbcon.ConnectionString = connectionString;\r
\r
- Console.WriteLine("open the connection...");\r
dbcon.Open();\r
\r
- Console.WriteLine("create SqliteCommand to CREATE TABLE MONO_TEST");\r
SqliteCommand dbcmd = new SqliteCommand();\r
dbcmd.Connection = dbcon;\r
\r
dbcmd.CommandText = \r
"CREATE TABLE MONO_TEST ( " +\r
"NID INT, " +\r
- "NDESC TEXT )";\r
- Console.WriteLine("execute command...");\r
- dbcmd.ExecuteNonQuery();\r
+ "NDESC TEXT, " +\r
+ "NTIME DATETIME); " +\r
+ "INSERT INTO MONO_TEST " +\r
+ "(NID, NDESC, NTIME )"+\r
+ "VALUES(1,'One', '2006-01-01')";\r
+ Console.WriteLine("Create & insert modified rows = 1: " + dbcmd.ExecuteNonQuery());\r
\r
- Console.WriteLine("set and execute command to INSERT INTO MONO_TEST");\r
dbcmd.CommandText =\r
"INSERT INTO MONO_TEST " +\r
- "(NID, NDESC )"+\r
- "VALUES(5,'Mono')";\r
- dbcmd.ExecuteNonQuery();\r
+ "(NID, NDESC, NTIME )"+\r
+ "VALUES(2,'Two', '2006-01-02')";\r
+ Console.WriteLine("Insert modified rows and ID = 1, 2: " + dbcmd.ExecuteNonQuery() + " , " + dbcmd.LastInsertRowID());\r
\r
- Console.WriteLine("set command to SELECT FROM MONO_TEST");\r
dbcmd.CommandText =\r
"SELECT * FROM MONO_TEST";\r
SqliteDataReader reader;\r
- Console.WriteLine("execute reader...");\r
reader = dbcmd.ExecuteReader();\r
\r
Console.WriteLine("read and display data...");\r
- while(reader.Read()) {\r
- Console.WriteLine("Data 1: " + reader[0].ToString());\r
- Console.WriteLine("Data 2: " + reader[1].ToString());\r
- }\r
+ while(reader.Read())\r
+ for (int i = 0; i < reader.FieldCount; i++)\r
+ Console.WriteLine(" Col {0}: {1} (type: {2}, data type: {3})",\r
+ i, reader[i].ToString(), reader[i].GetType().FullName, reader.GetDataTypeName(i));\r
+\r
+ dbcmd.CommandText = "SELECT NDESC FROM MONO_TEST WHERE NID=2";\r
+ Console.WriteLine("read and display a scalar = 'Two': " + dbcmd.ExecuteScalar());\r
+\r
+ dbcmd.CommandText = "SELECT count(*) FROM MONO_TEST";\r
+ Console.WriteLine("read and display a non-column scalar = 2: " + dbcmd.ExecuteScalar());\r
\r
Console.WriteLine("read and display data using DataAdapter...");\r
SqliteDataAdapter adapter = new SqliteDataAdapter("SELECT * FROM MONO_TEST", connectionString);\r
foreach(DataTable myTable in dataset.Tables){\r
foreach(DataRow myRow in myTable.Rows){\r
foreach (DataColumn myColumn in myTable.Columns){\r
- Console.WriteLine(myRow[myColumn]);\r
+ Console.WriteLine(" " + myRow[myColumn]);\r
}\r
}\r
}\r
\r
- \r
- Console.WriteLine("clean up...");\r
+ try {\r
+ dbcmd.CommandText = "SELECT NDESC INVALID SYNTAX FROM MONO_TEST WHERE NID=2";\r
+ dbcmd.ExecuteNonQuery();\r
+ Console.WriteLine("Should not reach here.");\r
+ } catch (Exception e) {\r
+ Console.WriteLine("Testing a syntax error: " + e.GetType().Name + ": " + e.Message);\r
+ }\r
+\r
+ /*try {\r
+ dbcmd.CommandText = "SELECT 0/0 FROM MONO_TEST WHERE NID=2";\r
+ Console.WriteLine("Should not reach here: " + dbcmd.ExecuteScalar());\r
+ } catch (Exception e) {\r
+ Console.WriteLine("Testing an execution error: " + e.GetType().Name + ": " + e.Message);\r
+ }*/\r
+\r
dataset.Dispose();\r
adapter.Dispose();\r
reader.Close();\r
dbcmd.Dispose();\r
dbcon.Close();\r
-\r
- Console.WriteLine("Done.");\r
}\r
}\r
}\r
Mono.Data.SqliteClient/SqliteRowUpdatedEventHandler.cs
Mono.Data.SqliteClient/SqliteRowUpdatingEventArgs.cs
Mono.Data.SqliteClient/SqliteRowUpdatingEventHandler.cs
-Mono.Data.SqliteClient/SqliteTransaction.cs
\ No newline at end of file
+Mono.Data.SqliteClient/SqliteTransaction.cs
+Mono.Data.SqliteClient/SqliteExceptions.cs