Replace SIZEOF_REGISTER with sizeof(mgreg_t) for consistency with sizeof(gpointer)
[mono.git] / mcs / class / Mono.Data.Sqlite / Mono.Data.Sqlite / Sqlite.cs
1 //
2 // Mono.Data.Sqlite.Sqlite.cs
3 //
4 // Provides C# bindings to the library sqlite.dll
5 //
6 //              Everaldo Canuto  <everaldo_canuto@yahoo.com.br>
7 //                      Chris Turchin <chris@turchin.net>
8 //                      Jeroen Zwartepoorte <jeroen@xs4all.nl>
9 //                      Thomas Zoechling <thomas.zoechling@gmx.at>
10 //
11 // Copyright (C) 2004  Everaldo Canuto
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 #if !NET_2_0
33 using System;
34 using System.Security;
35 using System.Runtime.InteropServices;
36 using System.Text;
37
38 namespace Mono.Data.Sqlite
39 {
40         /// <summary>
41         /// Represents the return values for sqlite_exec() and sqlite_step()
42         /// </summary>
43         internal enum SqliteError : int {
44                 /// <value>Successful result</value>
45                 OK        =  0,
46                 /// <value>SQL error or missing database</value>
47                 ERROR     =  1,
48                 /// <value>An internal logic error in SQLite</value>
49                 INTERNAL  =  2,
50                 /// <value>Access permission denied</value>
51                 PERM      =  3,
52                 /// <value>Callback routine requested an abort</value>
53                 ABORT     =  4,
54                 /// <value>The database file is locked</value>
55                 BUSY      =  5,
56                 /// <value>A table in the database is locked</value>
57                 LOCKED    =  6,
58                 /// <value>A malloc() failed</value>
59                 NOMEM     =  7,
60                 /// <value>Attempt to write a readonly database</value>
61                 READONLY  =  8,
62                 /// <value>Operation terminated by public const int interrupt()</value>
63                 INTERRUPT =  9,
64                 /// <value>Some kind of disk I/O error occurred</value>
65                 IOERR     = 10,
66                 /// <value>The database disk image is malformed</value>
67                 CORRUPT   = 11,
68                 /// <value>(Internal Only) Table or record not found</value>
69                 NOTFOUND  = 12,
70                 /// <value>Insertion failed because database is full</value>
71                 FULL      = 13,
72                 /// <value>Unable to open the database file</value>
73                 CANTOPEN  = 14,
74                 /// <value>Database lock protocol error</value>
75                 PROTOCOL  = 15,
76                 /// <value>(Internal Only) Database table is empty</value>
77                 EMPTY     = 16,
78                 /// <value>The database schema changed</value>
79                 SCHEMA    = 17,
80                 /// <value>Too much data for one row of a table</value>
81                 TOOBIG    = 18,
82                 /// <value>Abort due to contraint violation</value>
83                 CONSTRAINT= 19,
84                 /// <value>Data type mismatch</value>
85                 MISMATCH  = 20,
86                 /// <value>Library used incorrectly</value>
87                 MISUSE    = 21,
88                 /// <value>Uses OS features not supported on host</value>
89                 NOLFS     = 22,
90                 /// <value>Authorization denied</value>
91                 AUTH      = 23,
92                 /// <value>Auxiliary database format error</value>
93                 FORMAT    = 24,
94                 /// <value>2nd parameter to sqlite_bind out of range</value>
95                 RANGE     = 25,
96                 /// <value>File opened that is not a database file</value>
97                 NOTADB    = 26,
98                 /// <value>sqlite_step() has another row ready</value>
99                 ROW       = 100,
100                 /// <value>sqlite_step() has finished executing</value>
101                 DONE      = 101
102         }
103
104         /// <summary>
105         /// Provides the core of C# bindings to the library sqlite.dll
106         /// </summary>
107         internal sealed class Sqlite {
108
109                 #region PInvoke Functions
110                 
111                 [DllImport("sqlite")]
112                 internal static extern IntPtr sqlite_open (string dbname, int db_mode, out IntPtr errstr);
113
114                 [DllImport("sqlite")]
115                 internal static extern void sqlite_close (IntPtr sqlite_handle);
116
117                 [DllImport("sqlite")]
118                 internal static extern int sqlite_changes (IntPtr handle);
119
120                 [DllImport("sqlite")]
121                 internal static extern int sqlite_last_insert_rowid (IntPtr sqlite_handle);
122
123                 [DllImport ("sqlite")]
124                 internal static extern void sqliteFree (IntPtr ptr);
125                 
126                 [DllImport ("sqlite")]
127                 internal static extern SqliteError sqlite_compile (IntPtr sqlite_handle, IntPtr zSql, out IntPtr pzTail, out IntPtr pVm, out IntPtr errstr);
128
129                 [DllImport ("sqlite")]
130                 internal static extern SqliteError sqlite_step (IntPtr pVm, out int pN, out IntPtr pazValue, out IntPtr pazColName);
131
132                 [DllImport ("sqlite")]
133                 internal static extern SqliteError sqlite_finalize (IntPtr pVm, out IntPtr pzErrMsg);
134
135                 [DllImport ("sqlite")]
136                 internal static extern SqliteError sqlite_exec (IntPtr handle, string sql, IntPtr callback, IntPtr user_data, out IntPtr errstr_ptr);
137                 
138                 [DllImport ("sqlite")]
139                 internal static extern void sqlite_busy_timeout (IntPtr handle, int ms);
140
141                 [DllImport("sqlite3", CharSet = CharSet.Unicode)]
142                 internal static extern int sqlite3_open16 (string dbname, out IntPtr handle);
143
144                 [DllImport("sqlite3")]
145                 internal static extern void sqlite3_close (IntPtr sqlite_handle);
146
147                 [DllImport("sqlite3")]
148                 internal static extern IntPtr sqlite3_errmsg16 (IntPtr sqlite_handle);
149
150                 [DllImport("sqlite3")]
151                 internal static extern int sqlite3_changes (IntPtr handle);
152
153                 [DllImport("sqlite3")]
154                 internal static extern long sqlite3_last_insert_rowid (IntPtr sqlite_handle);
155
156                 [DllImport ("sqlite3")]
157                 internal static extern SqliteError sqlite3_prepare16 (IntPtr sqlite_handle, IntPtr zSql, int zSqllen, out IntPtr pVm, out IntPtr pzTail);
158
159                 [DllImport ("sqlite3")]
160                 internal static extern SqliteError sqlite3_step (IntPtr pVm);
161
162                 [DllImport ("sqlite3")]
163                 internal static extern SqliteError sqlite3_finalize (IntPtr pVm);
164
165                 [DllImport ("sqlite3")]
166                 internal static extern SqliteError sqlite3_exec (IntPtr handle, string sql, IntPtr callback, IntPtr user_data, out IntPtr errstr_ptr);
167         
168                 [DllImport ("sqlite3")]
169                 internal static extern IntPtr sqlite3_column_name16 (IntPtr pVm, int col);
170                 
171                 [DllImport ("sqlite3")]
172                 internal static extern IntPtr sqlite3_column_text16 (IntPtr pVm, int col);
173                 
174                 [DllImport ("sqlite3")]
175                 internal static extern IntPtr sqlite3_column_blob (IntPtr pVm, int col);
176                 
177                 [DllImport ("sqlite3")]
178                 internal static extern int sqlite3_column_bytes16 (IntPtr pVm, int col);
179                 
180                 [DllImport ("sqlite3")]
181                 internal static extern int sqlite3_column_count (IntPtr pVm);
182                 
183                 [DllImport ("sqlite3")]
184                 internal static extern int sqlite3_column_type (IntPtr pVm, int col);
185                 
186                 [DllImport ("sqlite3")]
187                 internal static extern Int64 sqlite3_column_int64 (IntPtr pVm, int col);
188                 
189                 [DllImport ("sqlite3")]
190                 internal static extern double sqlite3_column_double (IntPtr pVm, int col);
191                 
192                 [DllImport ("sqlite3")]
193                 internal static extern IntPtr sqlite3_column_decltype16 (IntPtr pVm, int col);
194
195                 [DllImport ("sqlite3")]
196                 internal static extern int sqlite3_bind_parameter_count (IntPtr pStmt);
197
198                 [DllImport ("sqlite3")]
199                 internal static extern IntPtr sqlite3_bind_parameter_name (IntPtr pStmt, int n); // UTF-8 encoded return
200
201                 [DllImport ("sqlite3")]
202                 internal static extern SqliteError sqlite3_bind_blob (IntPtr pStmt, int n, byte[] blob, int length, IntPtr freetype);
203
204                 [DllImport ("sqlite3")]
205                 internal static extern SqliteError sqlite3_bind_double (IntPtr pStmt, int n, double value);
206
207                 [DllImport ("sqlite3")]
208                 internal static extern SqliteError sqlite3_bind_int (IntPtr pStmt, int n, int value);
209
210                 [DllImport ("sqlite3")]
211                 internal static extern SqliteError sqlite3_bind_int64 (IntPtr pStmt, int n, long value);
212
213                 [DllImport ("sqlite3")]
214                 internal static extern SqliteError sqlite3_bind_null (IntPtr pStmt, int n);
215
216                 [DllImport ("sqlite3", CharSet = CharSet.Unicode)]
217                 internal static extern SqliteError sqlite3_bind_text16 (IntPtr pStmt, int n, string value, int length, IntPtr freetype);
218                 
219                 [DllImport ("sqlite3")]
220                 internal static extern void sqlite3_busy_timeout (IntPtr handle, int ms);
221
222                 #endregion
223                 
224                 // These are adapted from Mono.Unix.  When encoding is null,
225                 // use Ansi encoding, which is a superset of the default
226                 // expected encoding (ISO-8859-1).
227
228                 public static IntPtr StringToHeap (string s, Encoding encoding)
229                 {
230                         if (encoding == null)
231                                 return Marshal.StringToHGlobalAnsi (s);
232                                 
233                         int min_byte_count = encoding.GetMaxByteCount(1);
234                         char[] copy = s.ToCharArray ();
235                         byte[] marshal = new byte [encoding.GetByteCount (copy) + min_byte_count];
236
237                         int bytes_copied = encoding.GetBytes (copy, 0, copy.Length, marshal, 0);
238
239                         if (bytes_copied != (marshal.Length-min_byte_count))
240                                 throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
241
242                         IntPtr mem = Marshal.AllocHGlobal (marshal.Length);
243                         if (mem == IntPtr.Zero)
244                                 throw new OutOfMemoryException ();
245
246                         bool copied = false;
247                         try {
248                                 Marshal.Copy (marshal, 0, mem, marshal.Length);
249                                 copied = true;
250                         }
251                         finally {
252                                 if (!copied)
253                                         Marshal.FreeHGlobal (mem);
254                         }
255
256                         return mem;
257                 }
258
259                 public static unsafe string HeapToString (IntPtr p, Encoding encoding)
260                 {
261                         if (encoding == null)
262                                 return Marshal.PtrToStringAnsi (p);
263                 
264                         if (p == IntPtr.Zero)
265                                 return null;
266                                 
267                         // This assumes a single byte terminates the string.
268
269                         int len = 0;
270                         while (Marshal.ReadByte (p, len) != 0)
271                                 checked {++len;}
272
273                         string s = new string ((sbyte*) p, 0, len, encoding);
274                         len = s.Length;
275                         while (len > 0 && s [len-1] == 0)
276                                 --len;
277                         if (len == s.Length) 
278                                 return s;
279                         return s.Substring (0, len);
280                 }
281
282
283
284         }
285 }
286 #endif