/******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Runtime.InteropServices; using System.Collections.Generic; /// /// This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. /// internal abstract class SQLiteBase : SQLiteConvert, IDisposable { internal SQLiteBase(SQLiteDateFormats fmt) : base(fmt) {} /// /// Returns a string representing the active version of SQLite /// internal abstract string Version { get; } /// /// Returns the number of changes the last executing insert/update caused. /// internal abstract int Changes { get; } /// /// Opens a database. /// /// /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection /// to bind all attributed user-defined functions and collating sequences to the new connection. /// /// The filename of the database to open. SQLite automatically creates it if it doesn't exist. internal abstract void Open(string strFilename); /// /// Closes the currently-open database. /// /// /// After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated /// memory associated with the user-defined functions and collating sequences tied to the closed connection. /// internal abstract void Close(); /// /// Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command. /// /// The number of milliseconds to wait before returning SQLITE_BUSY internal abstract void SetTimeout(int nTimeoutMS); /// /// Quick execute of a SQL command. This is only executed internally, usually by SQLiteConnection when the connection /// is first opened to set the necessary startup pragmas. /// /// The SQL command text to execute internal abstract void Execute(string strSql); /// /// Returns the text of the last error issued by SQLite /// /// internal abstract string SQLiteLastError(); /// /// Prepares a SQL statement for execution. /// /// The SQL command text to prepare /// The previous statement in a multi-statement command, or null if no previous statement exists /// The remainder of the statement that was not processed. Each call to prepare parses the /// SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned /// here for a subsequent call to Prepare() until all the text has been processed. /// Returns an initialized SQLiteStatement. internal abstract SQLiteStatement Prepare(string strSql, SQLiteStatement previous, out string strRemain); /// /// Steps through a prepared statement. /// /// The SQLiteStatement to step through /// True if a row was returned, False if not. internal abstract bool Step(SQLiteStatement stmt); /// /// Finalizes a prepared statement. /// /// The statement to finalize internal abstract void FinalizeStatement(SQLiteStatement stmt); /// /// Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, /// transparently attempt to rebuild the SQL statement and throw an error if that was not possible. /// /// The statement to reset /// Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock internal abstract int Reset(SQLiteStatement stmt); internal abstract void Cancel(); /// /// An interop-specific function, this call sets an internal flag in the sqlite.interop.dll which causes all column names /// of subsequently-prepared statements to return in Database.Table.Column format, ignoring all aliases that may have been applied /// to tables or columns in a resultset. /// /// /// All statements prepared on this connection after this flag is changed are affected. Existing statements are not. /// /// Set to True to enable real column names, false to disable them. internal abstract void SetRealColNames(bool bOn); internal abstract void Bind_Double(SQLiteStatement stmt, int index, double value); internal abstract void Bind_Int32(SQLiteStatement stmt, int index, Int32 value); internal abstract void Bind_Int64(SQLiteStatement stmt, int index, Int64 value); internal abstract void Bind_Text(SQLiteStatement stmt, int index, string value); internal abstract void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData); internal abstract void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt); internal abstract void Bind_Null(SQLiteStatement stmt, int index); internal abstract int Bind_ParamCount(SQLiteStatement stmt); internal abstract string Bind_ParamName(SQLiteStatement stmt, int index); internal abstract int Bind_ParamIndex(SQLiteStatement stmt, string paramName); internal abstract int ColumnCount(SQLiteStatement stmt); internal abstract string ColumnName(SQLiteStatement stmt, int index); internal abstract string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity); internal abstract int ColumnIndex(SQLiteStatement stmt, string columnName); internal abstract double GetDouble(SQLiteStatement stmt, int index); internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); /// /// Helper function to retrieve a column of data from an active statement. /// /// The statement being step()'d through /// The column index to retrieve /// The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information. /// Returns the data in the column internal virtual object GetValue(SQLiteStatement stmt, int index, ref SQLiteType typ) { if (typ.Affinity == 0) typ = SQLiteConvert.ColumnToType(stmt, index); if (IsNull(stmt, index)) return DBNull.Value; Type t = SQLiteConvert.SQLiteTypeToType(typ); switch (TypeToAffinity(t)) { case TypeAffinity.Blob: int n = (int)GetBytes(stmt, index, 0, null, 0, 0); byte[] b = new byte[n]; GetBytes(stmt, index, 0, b, 0, n); return b; case TypeAffinity.DateTime: return GetDateTime(stmt, index); case TypeAffinity.Double: return Convert.ChangeType(GetDouble(stmt, index), t, null); case TypeAffinity.Int64: return Convert.ChangeType(GetInt64(stmt, index), t, null); default: return GetText(stmt, index); } } internal abstract int CreateCollation(string strCollation, SQLiteCollation func); internal abstract int CreateFunction(string strFunction, int nArgs, SQLiteCallback func, SQLiteCallback funcstep, SQLiteCallback funcfinal); internal abstract void FreeFunction(int nCookie); internal abstract int AggregateCount(int context); internal abstract int AggregateContext(int context); internal abstract long GetParamValueBytes(int ptr, int nDataOffset, byte[] bDest, int nStart, int nLength); internal abstract double GetParamValueDouble(int ptr); internal abstract int GetParamValueInt32(int ptr); internal abstract Int64 GetParamValueInt64(int ptr); internal abstract string GetParamValueText(int ptr); internal abstract TypeAffinity GetParamValueType(int ptr); internal abstract void ReturnBlob(int context, byte[] value); internal abstract void ReturnDouble(int context, double value); internal abstract void ReturnError(int context, string value); internal abstract void ReturnInt32(int context, Int32 value); internal abstract void ReturnInt64(int context, Int64 value); internal abstract void ReturnNull(int context); internal abstract void ReturnText(int context, string value); protected virtual void Dispose(bool bDisposing) { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } }