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) { db_version = 3; } catch (EntryPointNotFoundException) { 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; }
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; }
// 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); }
internal void ReadpVm(IntPtr pVm, int version, SqliteCommand cmd) { int pN; IntPtr pazValue; IntPtr pazColName; bool first = true; int[] declmode = null; while (true) { 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_decltype16(pVm, i); if (decl != IntPtr.Zero) { decltypes[i] = Marshal.PtrToStringUni(decl).ToLower(System.Globalization.CultureInfo.InvariantCulture); 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; if (version == 2) { IntPtr fieldPtr = Marshal.ReadIntPtr(pazColName, i * IntPtr.Size); colName = Sqlite.HeapToString(fieldPtr, ((SqliteConnection)cmd.Connection).Encoding); } else { colName = Marshal.PtrToStringUni(Sqlite.sqlite3_column_name16(pVm, i)); } columns[i] = colName; column_names_sens [colName] = i; column_names_insens [colName] = i; } } if (!hasdata) { break; } object[] data_row = new object [pN]; for (int i = 0; i < pN; i++) { if (version == 2) { IntPtr fieldPtr = Marshal.ReadIntPtr(pazValue, i * IntPtr.Size); data_row[i] = Sqlite.HeapToString(fieldPtr, ((SqliteConnection)cmd.Connection).Encoding); } else { switch (Sqlite.sqlite3_column_type(pVm, i)) { case 1: long val = Sqlite.sqlite3_column_int64(pVm, i); // 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 && val >= int.MinValue && val <= int.MaxValue) { data_row[i] = (int)val; } // Or if it was declared a date or datetime, do the reverse of what we // do for DateTime parameters. else if (declmode[i] == 2) { data_row[i] = DateTime.FromFileTime(val); } else { data_row[i] = val; } break; case 2: data_row[i] = Sqlite.sqlite3_column_double(pVm, i); break; case 3: data_row[i] = Marshal.PtrToStringUni(Sqlite.sqlite3_column_text16(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_bytes16(pVm, i); IntPtr blobptr = Sqlite.sqlite3_column_blob(pVm, i); byte[] blob = new byte[blobbytes]; Marshal.Copy(blobptr, blob, 0, blobbytes); data_row[i] = blob; break; case 5: data_row[i] = null; break; default: throw new ApplicationException("FATAL: Unknown sqlite3_column_type"); } } } rows.Add(data_row); } }
private string GetError3() { return(Marshal.PtrToStringUni(Sqlite.sqlite3_errmsg16(parent_conn.Handle))); }
public SqliteDataReader ExecuteReader(CommandBehavior behavior, bool want_results, out int rows_affected) { Prepare(); // 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; // pointer to SQL command // Sqlite 2 docs say this: By default, SQLite assumes that all data uses a fixed-size 8-bit // character (iso8859). But if you give the --enable-utf8 option to the configure script, then the // library assumes UTF-8 variable sized characters. This makes a difference for the LIKE and GLOB // operators and the LENGTH() and SUBSTR() functions. The static string sqlite_encoding will be set // to either "UTF-8" or "iso8859" to indicate how the library was compiled. In addition, the sqlite.h // header file will define one of the macros SQLITE_UTF8 or SQLITE_ISO8859, as appropriate. // // We have no way of knowing whether Sqlite 2 expects ISO8859 or UTF-8, but ISO8859 seems to be the // default. Therefore, we need to use an ISO8859(-1) compatible encoding, like ANSI. // OTOH, the user may want to specify the encoding of the bytes stored in the database, regardless // of what Sqlite is treating them as, // For Sqlite 3, we use the UTF-16 prepare function, so we need a UTF-16 string. if (parent_conn.Version == 2) { psql = Sqlite.StringToHeap(sql.Trim(), parent_conn.Encoding); } else { psql = Marshal.StringToHGlobalUni(sql.Trim()); } IntPtr pzTail = psql; IntPtr errMsgPtr; parent_conn.StartExec(); rows_affected = 0; try { while (true) { IntPtr pStmt; GetNextStatement(pzTail, out pzTail, out pStmt); if (pStmt == IntPtr.Zero) { throw new Exception(); } // 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(); Marshal.FreeHGlobal(psql); } }
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.HeapToString(Sqlite.sqlite3_bind_parameter_name(pStmt, i), Encoding.UTF8); SqliteParameter param = null; if (name != null) { param = sql_params[name] as SqliteParameter; } else { param = sql_params[i - 1] as SqliteParameter; } if (param.Value == null) { Sqlite.sqlite3_bind_null(pStmt, i); continue; } Type ptype = param.Value.GetType(); if (ptype.IsEnum) { ptype = Enum.GetUnderlyingType(ptype); } SqliteError err; if (ptype.Equals(typeof(String))) { String s = (String)param.Value; err = Sqlite.sqlite3_bind_text16(pStmt, i, s, -1, (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.IsEnum) { err = Sqlite.sqlite3_bind_int(pStmt, i, (Int32)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 if (ptype.Equals(typeof(Byte[]))) { err = Sqlite.sqlite3_bind_blob(pStmt, i, (Byte[])param.Value, ((Byte[])param.Value).Length, (IntPtr)(-1)); } else { throw new ApplicationException("Unkown Parameter Type"); } if (err != SqliteError.OK) { throw new ApplicationException("Sqlite error in bind " + err); } } }