* Mono.Posix.dll.sources: Rename Mono.Posix to Mono.Unix.
[mono.git] / mcs / class / Mono.Data.SqliteClient / Mono.Data.SqliteClient / SqliteCommand.cs
1 //
2 // Mono.Data.SqliteClient.SqliteCommand.cs
3 //
4 // Represents a Transact-SQL statement or stored procedure to execute against 
5 // a Sqlite database file.
6 //
7 // Author(s): Vladimir Vukicevic  <vladimir@pobox.com>
8 //            Everaldo Canuto  <everaldo_canuto@yahoo.com.br>
9 //
10 // Copyright (C) 2002  Vladimir Vukicevic
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Text;
34 using System.Runtime.InteropServices;
35 using System.Data;
36
37 namespace Mono.Data.SqliteClient 
38 {
39         public class SqliteCommand : IDbCommand
40         {
41
42                 #region Fields
43                 
44                 private SqliteConnection parent_conn;
45                 //private SqliteTransaction transaction;
46                 private IDbTransaction transaction;
47                 private string sql;
48                 private int timeout;
49                 private CommandType type;
50                 private UpdateRowSource upd_row_source;
51                 private SqliteParameterCollection sql_params;
52                 
53                 #endregion
54
55                 #region Constructors and destructors
56                 
57                 public SqliteCommand ()
58                 {
59                         sql = "";
60                         sql_params = new SqliteParameterCollection ();
61                 }
62                 
63                 public SqliteCommand (string sqlText)
64                 {
65                         sql = sqlText;
66                         sql_params = new SqliteParameterCollection ();
67                 }
68                 
69                 public SqliteCommand (string sqlText, SqliteConnection dbConn)
70                 {
71                         sql = sqlText;
72                         parent_conn = dbConn;
73                         sql_params = new SqliteParameterCollection ();
74                 }
75                 
76                 public SqliteCommand (string sqlText, SqliteConnection dbConn, IDbTransaction trans)
77                 {
78                         sql = sqlText;
79                         parent_conn = dbConn;
80                         transaction = trans;
81                         sql_params = new SqliteParameterCollection ();
82                 }
83                 
84                 public void Dispose ()
85                 {
86                 }
87                 
88                 #endregion
89
90                 #region Properties
91                 
92                 public string CommandText {
93                         get { return sql; }
94                         set { sql = value; }
95                 }
96                 
97                 public int CommandTimeout {
98                         get { return timeout; }
99                         set { timeout = value; }
100                 }
101                 
102                 public CommandType CommandType {
103                         get { return type; }
104                         set { type = value; }
105                 }
106                 
107                 IDbConnection IDbCommand.Connection {
108                         get { return parent_conn; }
109                         set {
110                                         if (!(value is SqliteConnection)) {
111                                                 throw new InvalidOperationException ("Can't set Connection to something other than a SqliteConnection");
112                                         }
113                                         parent_conn = (SqliteConnection) value;
114                         }
115                 }
116                 
117                 public SqliteConnection Connection {
118                         get { return parent_conn; }
119                         set { parent_conn = value; }
120                 }
121                 
122                 IDataParameterCollection IDbCommand.Parameters {
123                         get { return Parameters; }
124                 }
125                 
126                 public SqliteParameterCollection Parameters {
127                         get { return sql_params; }
128                 }
129                 
130                 public IDbTransaction Transaction {
131                         get { return transaction; }
132                         set { transaction = value; }
133                 }
134                 
135                 public UpdateRowSource UpdatedRowSource {
136                         get { return upd_row_source; }
137                         set { upd_row_source = value; }
138                 }
139                                 
140                 #endregion
141
142                 #region Internal Methods
143                 
144                 internal int NumChanges () 
145                 {
146                         if (parent_conn.Version == 3)
147                                 return Sqlite.sqlite3_changes(parent_conn.Handle);
148                         else
149                                 return Sqlite.sqlite_changes(parent_conn.Handle);
150                 }
151                 
152                 #endregion
153
154                 #region Public Methods
155                 
156                 public void Cancel ()
157                 {
158                 }
159                 
160                 public void Prepare ()
161                 {
162                 }
163                 
164                 IDbDataParameter IDbCommand.CreateParameter ()
165                 {
166                         return CreateParameter ();
167                 }
168                 
169                 public SqliteParameter CreateParameter ()
170                 {
171                         return new SqliteParameter ();
172                 }
173                 
174                 public int ExecuteNonQuery ()
175                 {
176                         int rows_affected;
177                         SqliteDataReader r = ExecuteReader (CommandBehavior.Default, false, out rows_affected);
178                         return rows_affected;
179                 }
180                 
181                 public object ExecuteScalar ()
182                 {
183                         SqliteDataReader r = ExecuteReader ();
184                         if (r == null || !r.Read ()) {
185                                 return null;
186                         }
187                         object o = r[0];
188                         r.Close ();
189                         return o;
190                 }
191                 
192                 IDataReader IDbCommand.ExecuteReader ()
193                 {
194                         return ExecuteReader ();
195                 }
196                 
197                 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
198                 {
199                         return ExecuteReader (behavior);
200                 }
201                 
202                 public SqliteDataReader ExecuteReader ()
203                 {
204                         return ExecuteReader (CommandBehavior.Default);
205                 }
206                 
207                 public SqliteDataReader ExecuteReader (CommandBehavior behavior)
208                 {
209                         int r;
210                         return ExecuteReader (behavior, true, out r);
211                 }
212                 
213                 public SqliteDataReader ExecuteReader (CommandBehavior behavior, bool want_results, out int rows_affected)
214                 {
215                         SqliteDataReader reader = null;
216                         SqliteError err = SqliteError.OK;
217                         IntPtr errMsg = IntPtr.Zero; 
218                         
219                         parent_conn.StartExec ();
220                         
221                         string msg = "";
222
223                         try {
224                                 if (want_results) {
225                                         IntPtr pVm = IntPtr.Zero;
226                                         IntPtr pzTail = IntPtr.Zero;
227                                         if (parent_conn.Version == 3)
228                                                 err = Sqlite.sqlite3_prepare (parent_conn.Handle, sql, sql.Length, out pVm, out pVm);
229                                         else
230                                                 err = Sqlite.sqlite_compile (parent_conn.Handle, sql, out pzTail, out pVm, out errMsg);
231                                         if (err == SqliteError.OK)
232                                                 reader = new SqliteDataReader (this, pVm, parent_conn.Version);
233                                         if (parent_conn.Version == 3)
234                                                 err = Sqlite.sqlite3_finalize (pVm, out errMsg);
235                                         else
236                                                 err = Sqlite.sqlite_finalize (pVm, out errMsg);
237                                 } else {
238                                         if (parent_conn.Version == 3)
239                                                 err = Sqlite.sqlite3_exec (parent_conn.Handle, sql, IntPtr.Zero, IntPtr.Zero, out errMsg);
240                                         else
241                                                 err = Sqlite.sqlite_exec (parent_conn.Handle, sql, IntPtr.Zero, IntPtr.Zero, out errMsg);
242                                 }
243                         } finally {                     
244                                 parent_conn.EndExec ();
245                         }
246
247                         if (err != SqliteError.OK) {
248                                 if (errMsg != IntPtr.Zero) {
249                                         msg = Marshal.PtrToStringAnsi (errMsg);
250                                         if (parent_conn.Version == 3)
251                                                 Sqlite.sqlite3Free (errMsg);
252                                         else
253                                                 Sqlite.sqliteFree (errMsg);
254                                 }
255                                 throw new ApplicationException ("Sqlite error " + msg);
256                         }
257                         
258                         rows_affected = NumChanges ();
259                         
260                         return reader;
261                 }
262                 
263                 public int LastInsertRowID () 
264                 {
265                         if (parent_conn.Version == 3)
266                                 return Sqlite.sqlite3_last_insert_rowid(parent_conn.Handle);
267                         else
268                                 return Sqlite.sqlite_last_insert_rowid(parent_conn.Handle);
269                 }
270                 
271                 #endregion
272
273         }
274 }