1 // -*- c-basic-offset: 8; inent-tabs-mode: nil -*-
5 // Author(s): Vladimir Vukicevic <vladimir@pobox.com>
7 // 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.
33 using System.Runtime.InteropServices;
36 namespace Mono.Data.SqliteClient {
37 public class SqliteCommand : IDbCommand
39 SqliteConnection parent_conn;
40 // SqliteTransaction transaction;
41 IDbTransaction transaction;
45 UpdateRowSource upd_row_source;
46 SqliteParameterCollection sql_params;
48 public SqliteCommand ()
51 sql_params = new SqliteParameterCollection ();
54 public SqliteCommand (string sqlText, SqliteConnection dbConn)
58 sql_params = new SqliteParameterCollection ();
61 public SqliteCommand (string sqlText, SqliteConnection dbConn, IDbTransaction trans)
66 sql_params = new SqliteParameterCollection ();
69 public void Dispose ()
73 public string CommandText {
82 // note that we could actually implement
83 // a timeout with sqlite, but setting up a signal to interrupt us after
84 // a certain amount of time, but it's probably not worth the effort
85 public int CommandTimeout {
94 IDbConnection IDbCommand.Connection {
99 if (!(value is SqliteConnection)) {
100 throw new InvalidOperationException ("Can't set Connection to something other than a SqliteConnection");
102 parent_conn = (SqliteConnection) value;
106 public SqliteConnection Connection {
115 public CommandType CommandType {
124 IDataParameterCollection IDbCommand.Parameters {
130 public SqliteParameterCollection Parameters {
136 public IDbTransaction Transaction {
145 public UpdateRowSource UpdatedRowSource {
147 return upd_row_source;
150 upd_row_source = value;
154 public void Prepare ()
158 public void Cancel ()
162 IDbDataParameter IDbCommand.CreateParameter ()
164 return CreateParameter ();
167 public SqliteParameter CreateParameter ()
169 return new SqliteParameter ();
172 public int ExecuteNonQuery ()
175 SqliteDataReader r = ExecuteReader (CommandBehavior.Default, false, out rows_affected);
176 return rows_affected;
179 public object ExecuteScalar ()
181 SqliteDataReader r = ExecuteReader ();
182 if (r == null || !r.Read ()) {
190 IDataReader IDbCommand.ExecuteReader ()
192 return ExecuteReader ();
195 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
197 return ExecuteReader (behavior);
200 public SqliteDataReader ExecuteReader ()
202 return ExecuteReader (CommandBehavior.Default);
205 public SqliteDataReader ExecuteReader (CommandBehavior behavior)
208 return ExecuteReader (behavior, true, out r);
211 public SqliteDataReader ExecuteReader (CommandBehavior behavior, bool want_results, out int rows_affected)
213 SqliteDataReader reader = null;
216 parent_conn.StartExec ();
224 reader = new SqliteDataReader (this);
226 err = sqlite_exec (parent_conn.Handle,
228 new SqliteCallbackFunction (reader.SqliteCallback),
229 IntPtr.Zero, &msg_result);
230 reader.ReadingDone ();
232 err = sqlite_exec (parent_conn.Handle,
235 IntPtr.Zero, &msg_result);
238 parent_conn.EndExec ();
241 if (msg_result != null){
242 StringBuilder sb = new StringBuilder ();
244 for (byte *y = msg_result; *y != 0; y++)
245 sb.Append ((char) *y);
246 msg = sb.ToString ();
248 sqliteFree (msg_result);
252 if (err != SqliteError.OK)
253 throw new ApplicationException ("Sqlite error " + msg);
255 rows_affected = NumChanges ();
260 internal int NumChanges () {
261 return sqlite_changes (parent_conn.Handle);
264 public int LastInsertRowID () {
265 return sqlite_last_insert_rowid (parent_conn.Handle);
268 internal unsafe delegate int SqliteCallbackFunction (ref object o, int argc, sbyte **argv, sbyte **colnames);
270 [DllImport("sqlite")]
271 unsafe static extern SqliteError sqlite_exec (IntPtr handle, string sql, SqliteCallbackFunction callback,
272 IntPtr user_data, byte **errstr_ptr);
274 [DllImport ("sqlite")]
275 unsafe static extern void sqliteFree (void *ptr);
277 [DllImport("sqlite")]
278 static extern int sqlite_changes (IntPtr handle);
280 [DllImport("sqlite")]
281 static extern int sqlite_last_insert_rowid (IntPtr sqlite_handle);
283 internal enum SqliteError : int {