/// <summary> /// Initializes the statement and attempts to get all information about parameters in the statement /// </summary> /// <param name="sqlbase">The base SQLite object</param> /// <param name="flags">The flags associated with the parent connection object</param> /// <param name="stmt">The statement</param> /// <param name="strCommand">The command text for this statement</param> /// <param name="previous">The previous command in a multi-statement command</param> internal SQLiteStatement(SQLiteBase sqlbase, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; _sqlStatement = strCommand; _flags = flags; // Determine parameters for this statement (if any) and prepare space for them. int nCmdStart = 0; int n = _sql.Bind_ParamCount(this, _flags); int x; string s; if (n > 0) { if (previous != null) nCmdStart = previous._unnamedParameters; _paramNames = new string[n]; _paramValues = new SQLiteParameter[n]; for (x = 0; x < n; x++) { s = _sql.Bind_ParamName(this, _flags, x + 1); if (String.IsNullOrEmpty(s)) { s = String.Format(CultureInfo.InvariantCulture, ";{0}", nCmdStart); nCmdStart++; _unnamedParameters++; } _paramNames[x] = s; _paramValues[x] = null; } } }
/// <summary> /// Builds an array of prepared statements for each complete SQL statement in the command text /// </summary> internal SQLiteStatement BuildNextCommand() { SQLiteStatement stmt = null; try { if ((_cnn != null) && (_cnn._sql != null)) { if (_statementList == null) { _remainingText = _commandText; } stmt = _cnn._sql.Prepare(_cnn, _remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], (uint)(_commandTimeout * 1000), out _remainingText); if (stmt != null) { stmt._command = this; if (_statementList == null) { _statementList = new List <SQLiteStatement>(); } _statementList.Add(stmt); _parameterCollection.MapParameters(stmt); stmt.BindParameters(); } } return(stmt); } catch (Exception) { if (stmt != null) { if ((_statementList != null) && _statementList.Contains(stmt)) { _statementList.Remove(stmt); } stmt.Dispose(); } // If we threw an error compiling the statement, we cannot continue on so set the remaining text to null. _remainingText = null; throw; } }
internal override DateTime GetDateTime(SQLiteStatement stmt, int index) { if (_datetimeFormat == SQLiteDateFormats.Ticks) { return(ToDateTime(GetInt64(stmt, index), _datetimeKind)); } else if (_datetimeFormat == SQLiteDateFormats.JulianDay) { return(ToDateTime(GetDouble(stmt, index), _datetimeKind)); } else if (_datetimeFormat == SQLiteDateFormats.UnixEpoch) { return(ToDateTime(GetInt32(stmt, index), _datetimeKind)); } return(ToDateTime(GetText(stmt, index))); }
internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1)); if (n != SQLiteErrorCode.Ok) { throw new SQLiteException(n, GetLastError()); } }
internal override string ColumnName(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; IntPtr p = UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index, out len); #else IntPtr p = UnsafeNativeMethods.sqlite3_column_name16(stmt._sqlite_stmt, index); #endif if (p == IntPtr.Zero) { throw new SQLiteException(SQLiteErrorCode.NoMem, GetLastError()); } #if !SQLITE_STANDARD return(UTF16ToString(p, len)); #else return(UTF16ToString(p, -1)); #endif }
/////////////////////////////////////////////////////////////////////////////////////////////// private void DisposeStatements() { if (_statementList == null) { return; } int x = _statementList.Count; for (int n = 0; n < x; n++) { SQLiteStatement stmt = _statementList[n]; if (stmt == null) { continue; } stmt.Dispose(); } _statementList = null; }
internal override string ColumnTableName(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16_interop(stmt._sqlite_stmt, index, out len), len); #else return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16(stmt._sqlite_stmt, index), -1); #endif }
internal override string ColumnName(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; IntPtr p = UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index, out len); #else IntPtr p = UnsafeNativeMethods.sqlite3_column_name16(stmt._sqlite_stmt, index); #endif if (p == IntPtr.Zero) throw new SQLiteException(SQLiteErrorCode.NoMem, GetLastError()); #if !SQLITE_STANDARD return UTF16ToString(p, len); #else return UTF16ToString(p, -1); #endif }
internal override TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index) { return UnsafeNativeMethods.sqlite3_column_type(stmt._sqlite_stmt, index); }
internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain) { if (!String.IsNullOrEmpty(strSql)) { // // NOTE: SQLite does not support the concept of separate schemas // in one database; therefore, remove the base schema name // used to smooth integration with the base .NET Framework // data classes. // string baseSchemaName = (cnn != null) ? cnn._baseSchemaName : null; if (!String.IsNullOrEmpty(baseSchemaName)) { strSql = strSql.Replace( String.Format(CultureInfo.InvariantCulture, "[{0}].", baseSchemaName), String.Empty); strSql = strSql.Replace( String.Format(CultureInfo.InvariantCulture, "{0}.", baseSchemaName), String.Empty); } } SQLiteConnectionFlags flags = (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default; if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare) { if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0)) SQLiteLog.LogMessage("Preparing {<nothing>}..."); else SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Preparing {{{0}}}...", strSql)); } IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int len = 0; SQLiteErrorCode n = SQLiteErrorCode.Schema; int retries = 0; byte[] b = ToUTF8(strSql); string typedefs = null; SQLiteStatement cmd = null; Random rnd = null; uint starttick = (uint)Environment.TickCount; GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned); IntPtr psql = handle.AddrOfPinnedObject(); SQLiteStatementHandle statementHandle = null; try { while ((n == SQLiteErrorCode.Schema || n == SQLiteErrorCode.Locked || n == SQLiteErrorCode.Busy) && retries < 3) { try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len); #else #if USE_PREPARE_V2 n = UnsafeNativeMethods.sqlite3_prepare_v2(_sql, psql, b.Length - 1, out stmt, out ptr); #else n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); #endif len = -1; #endif #if !NET_COMPACT_20 && TRACE_STATEMENT Trace.WriteLine(String.Format("Prepare ({0}): {1}", n, stmt)); #endif if ((n == SQLiteErrorCode.Ok) && (stmt != IntPtr.Zero)) { if (statementHandle != null) statementHandle.Dispose(); statementHandle = new SQLiteStatementHandle(_sql, stmt); } } if (statementHandle != null) { SQLiteConnection.OnChanged(null, new ConnectionEventArgs( SQLiteConnectionEventType.NewCriticalHandle, null, null, null, null, statementHandle, strSql, new object[] { cnn, strSql, previous, timeoutMS })); } if (n == SQLiteErrorCode.Schema) retries++; else if (n == SQLiteErrorCode.Error) { if (String.Compare(GetLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0) { int pos = strSql.IndexOf(';'); if (pos == -1) pos = strSql.Length - 1; typedefs = strSql.Substring(0, pos + 1); strSql = strSql.Substring(pos + 1); strRemain = ""; while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } if (cmd != null) cmd.SetTypes(typedefs); return cmd; } #if (NET_35 || NET_40 || NET_45 || NET_451) && !PLATFORM_COMPACTFRAMEWORK else if (_buildingSchema == false && String.Compare(GetLastError(), 0, "no such table: TEMP.SCHEMA", 0, 26, StringComparison.OrdinalIgnoreCase) == 0) { strRemain = ""; _buildingSchema = true; try { ISQLiteSchemaExtensions ext = ((IServiceProvider)DenverDBFactory.Instance).GetService(typeof(ISQLiteSchemaExtensions)) as ISQLiteSchemaExtensions; if (ext != null) ext.BuildTempSchema(cnn); while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } return cmd; } finally { _buildingSchema = false; } } #endif } else if (n == SQLiteErrorCode.Locked || n == SQLiteErrorCode.Busy) // Locked -- delay a small amount before retrying { // Keep trying if (rnd == null) // First time we've encountered the lock rnd = new Random(); // If we've exceeded the command's timeout, give up and throw an error if ((uint)Environment.TickCount - starttick > timeoutMS) { throw new SQLiteException(n, GetLastError()); } else { // Otherwise sleep for a random amount of time up to 150ms System.Threading.Thread.Sleep(rnd.Next(1, 150)); } } } if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); strRemain = UTF8ToString(ptr, len); if (statementHandle != null) cmd = new SQLiteStatement(this, flags, statementHandle, strSql.Substring(0, strSql.Length - strRemain.Length), previous); return cmd; } finally { handle.Free(); } }
internal override bool Step(SQLiteStatement stmt) { SQLiteErrorCode n; Random rnd = null; uint starttick = (uint)Environment.TickCount; uint timeout = (uint)(stmt._command._commandTimeout * 1000); while (true) { n = UnsafeNativeMethods.sqlite3_step(stmt._sqlite_stmt); if (n == SQLiteErrorCode.Row) return true; if (n == SQLiteErrorCode.Done) return false; if (n != SQLiteErrorCode.Ok) { SQLiteErrorCode r; // An error occurred, attempt to reset the statement. If the reset worked because the // schema has changed, re-try the step again. If it errored our because the database // is locked, then keep retrying until the command timeout occurs. r = Reset(stmt); if (r == SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); else if ((r == SQLiteErrorCode.Locked || r == SQLiteErrorCode.Busy) && stmt._command != null) { // Keep trying if (rnd == null) // First time we've encountered the lock rnd = new Random(); // If we've exceeded the command's timeout, give up and throw an error if ((uint)Environment.TickCount - starttick > timeout) { throw new SQLiteException(r, GetLastError()); } else { // Otherwise sleep for a random amount of time up to 150ms System.Threading.Thread.Sleep(rnd.Next(1, 150)); } } } } }
internal override uint GetUInt32(SQLiteStatement stmt, int index) { return unchecked((uint)GetInt32(stmt, index)); }
internal override int GetInt32(SQLiteStatement stmt, int index) { return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index); }
internal override ushort GetUInt16(SQLiteStatement stmt, int index) { return unchecked((ushort)(GetInt32(stmt, index) & ushort.MaxValue)); }
internal override byte GetByte(SQLiteStatement stmt, int index) { return unchecked((byte)(GetInt32(stmt, index) & byte.MaxValue)); }
internal override int ColumnIndex(SQLiteStatement stmt, string columnName) { int x = ColumnCount(stmt); for (int n = 0; n < x; n++) { if (String.Compare(columnName, ColumnName(stmt, n), StringComparison.OrdinalIgnoreCase) == 0) return n; } return -1; }
internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity) { int len; #if !SQLITE_STANDARD IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype_interop(stmt._sqlite_stmt, index, out len); #else len = -1; IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype(stmt._sqlite_stmt, index); #endif nAffinity = ColumnAffinity(stmt, index); if (p != IntPtr.Zero) return UTF8ToString(p, len); else { string[] ar = stmt.TypeDefinitions; if (ar != null) { if (index < ar.Length && ar[index] != null) return ar[index]; } return String.Empty; //switch (nAffinity) //{ // case TypeAffinity.Int64: // return "BIGINT"; // case TypeAffinity.Double: // return "DOUBLE"; // case TypeAffinity.Blob: // return "BLOB"; // default: // return "TEXT"; //} } }
/// <summary> /// This function does all the nasty work at determining what keys need to be returned for /// a given statement. /// </summary> /// <param name="cnn"></param> /// <param name="reader"></param> /// <param name="stmt"></param> internal SQLiteKeyReader(SQLiteConnection cnn, SQLiteDataReader reader, SQLiteStatement stmt) { Dictionary <string, int> catalogs = new Dictionary <string, int>(); Dictionary <string, List <string> > tables = new Dictionary <string, List <string> >(); List <string> list; List <KeyInfo> keys = new List <KeyInfo>(); // Record the statement so we can use it later for sync'ing _stmt = stmt; // Fetch all the attached databases on this connection using (DataTable tbl = cnn.GetSchema("Catalogs")) { foreach (DataRow row in tbl.Rows) { catalogs.Add((string)row["CATALOG_NAME"], Convert.ToInt32(row["ID"], CultureInfo.InvariantCulture)); } } // Fetch all the unique tables and catalogs used by the current statement using (DataTable schema = reader.GetSchemaTable(false, false)) { foreach (DataRow row in schema.Rows) { // Check if column is backed to a table if (row[SchemaTableOptionalColumn.BaseCatalogName] == DBNull.Value) { continue; } // Record the unique table so we can look up its keys string catalog = (string)row[SchemaTableOptionalColumn.BaseCatalogName]; string table = (string)row[SchemaTableColumn.BaseTableName]; if (tables.ContainsKey(catalog) == false) { list = new List <string>(); tables.Add(catalog, list); } else { list = tables[catalog]; } if (list.Contains(table) == false) { list.Add(table); } } // For each catalog and each table, query the indexes for the table. // Find a primary key index if there is one. If not, find a unique index instead foreach (KeyValuePair <string, List <string> > pair in tables) { for (int i = 0; i < pair.Value.Count; i++) { string table = pair.Value[i]; DataRow preferredRow = null; using (DataTable tbl = cnn.GetSchema("Indexes", new string[] { pair.Key, null, table })) { // Loop twice. The first time looking for a primary key index, // the second time looking for a unique index for (int n = 0; n < 2 && preferredRow == null; n++) { foreach (DataRow row in tbl.Rows) { if (n == 0 && (bool)row["PRIMARY_KEY"] == true) { preferredRow = row; break; } else if (n == 1 && (bool)row["UNIQUE"] == true) { preferredRow = row; break; } } } if (preferredRow == null) // Unable to find any suitable index for this table so remove it { pair.Value.RemoveAt(i); i--; } else // We found a usable index, so fetch the necessary table details { using (DataTable tblTables = cnn.GetSchema("Tables", new string[] { pair.Key, null, table })) { // Find the root page of the table in the current statement and get the cursor that's iterating it int database = catalogs[pair.Key]; int rootPage = Convert.ToInt32(tblTables.Rows[0]["TABLE_ROOTPAGE"], CultureInfo.InvariantCulture); int cursor = stmt._sql.GetCursorForTable(stmt, database, rootPage); // Now enumerate the members of the index we're going to use using (DataTable indexColumns = cnn.GetSchema("IndexColumns", new string[] { pair.Key, null, table, (string)preferredRow["INDEX_NAME"] })) { KeyQuery query = null; List <string> cols = new List <string>(); for (int x = 0; x < indexColumns.Rows.Count; x++) { bool addKey = true; // If the column in the index already appears in the query, skip it foreach (DataRow row in schema.Rows) { if (row.IsNull(SchemaTableColumn.BaseColumnName)) { continue; } if ((string)row[SchemaTableColumn.BaseColumnName] == (string)indexColumns.Rows[x]["COLUMN_NAME"] && (string)row[SchemaTableColumn.BaseTableName] == table && (string)row[SchemaTableOptionalColumn.BaseCatalogName] == pair.Key) { indexColumns.Rows.RemoveAt(x); x--; addKey = false; break; } } if (addKey == true) { cols.Add((string)indexColumns.Rows[x]["COLUMN_NAME"]); } } // If the index is not a rowid alias, record all the columns // needed to make up the unique index and construct a SQL query for it if ((string)preferredRow["INDEX_NAME"] != "sqlite_master_PK_" + table) { // Whatever remains of the columns we need that make up the index that are not // already in the query need to be queried separately, so construct a subquery if (cols.Count > 0) { string[] querycols = new string[cols.Count]; cols.CopyTo(querycols); query = new KeyQuery(cnn, pair.Key, table, querycols); } } // Create a KeyInfo struct for each column of the index for (int x = 0; x < indexColumns.Rows.Count; x++) { string columnName = (string)indexColumns.Rows[x]["COLUMN_NAME"]; KeyInfo key = new KeyInfo(); key.rootPage = rootPage; key.cursor = cursor; key.database = database; key.databaseName = pair.Key; key.tableName = table; key.columnName = columnName; key.query = query; key.column = x; keys.Add(key); } } } } } } } } // Now we have all the additional columns we have to return in order to support // CommandBehavior.KeyInfo _keyInfo = new KeyInfo[keys.Count]; keys.CopyTo(_keyInfo); }
internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index) { SQLiteStatementHandle handle = stmt._sqlite_stmt; string name; #if !SQLITE_STANDARD int len; name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len); #else name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1); #endif if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Statement {0} paramter #{1} name is {{{2}}}.", handleIntPtr, index, name)); } return name; }
internal override long GetInt64(SQLiteStatement stmt, int index) { long value; #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index); #elif !SQLITE_STANDARD UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value); #else throw new NotImplementedException(); #endif return value; }
internal override SQLiteErrorCode Reset(SQLiteStatement stmt) { SQLiteErrorCode n; #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_reset_interop(stmt._sqlite_stmt); #else n = UnsafeNativeMethods.sqlite3_reset(stmt._sqlite_stmt); #endif // If the schema changed, try and re-prepare it if (n == SQLiteErrorCode.Schema) { // Recreate a dummy statement string str; using (SQLiteStatement tmp = Prepare(null, stmt._sqlStatement, null, (uint)(stmt._command._commandTimeout * 1000), out str)) { // Finalize the existing statement stmt._sqlite_stmt.Dispose(); // Reassign a new statement pointer to the old statement and clear the temporary one stmt._sqlite_stmt = tmp._sqlite_stmt; tmp._sqlite_stmt = null; // Reapply parameters stmt.BindParameters(); } return SQLiteErrorCode.Unknown; // Reset was OK, with schema change } else if (n == SQLiteErrorCode.Locked || n == SQLiteErrorCode.Busy) return n; if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); return n; // We reset OK, no schema changes }
internal override ulong GetUInt64(SQLiteStatement stmt, int index) { return unchecked((ulong)GetInt64(stmt, index)); }
/// <summary> /// Initializes the statement and attempts to get all information about parameters in the statement /// </summary> /// <param name="sqlbase">The base SQLite object</param> /// <param name="flags">The flags associated with the parent connection object</param> /// <param name="stmt">The statement</param> /// <param name="strCommand">The command text for this statement</param> /// <param name="previous">The previous command in a multi-statement command</param> internal SQLiteStatement(SQLiteBase sqlbase, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; _sqlStatement = strCommand; _flags = flags; // Determine parameters for this statement (if any) and prepare space for them. int nCmdStart = 0; int n = _sql.Bind_ParamCount(this, _flags); int x; string s; if (n > 0) { if (previous != null) { nCmdStart = previous._unnamedParameters; } _paramNames = new string[n]; _paramValues = new SQLiteParameter[n]; for (x = 0; x < n; x++) { s = _sql.Bind_ParamName(this, _flags, x + 1); if (String.IsNullOrEmpty(s)) { s = String.Format(CultureInfo.InvariantCulture, ";{0}", nCmdStart); nCmdStart++; _unnamedParameters++; } _paramNames[x] = s; _paramValues[x] = null; } } }
internal override DateTime GetDateTime(SQLiteStatement stmt, int index) { if (_datetimeFormat == SQLiteDateFormats.Ticks) return ToDateTime(GetInt64(stmt, index), _datetimeKind); else if (_datetimeFormat == SQLiteDateFormats.JulianDay) return ToDateTime(GetDouble(stmt, index), _datetimeKind); else if (_datetimeFormat == SQLiteDateFormats.UnixEpoch) return ToDateTime(GetInt32(stmt, index), _datetimeKind); #if !SQLITE_STANDARD int len; return ToDateTime(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len); #else return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index)); #endif }
internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName)); if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Statement {0} paramter index of name {{{1}}} is #{2}.", handleIntPtr, paramName, index)); } return index; }
internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1)); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); }
internal override long GetBytes(SQLiteStatement stmt, int index, int nDataOffset, byte[] bDest, int nStart, int nLength) { int nlen = UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index); // If no destination buffer, return the size needed. if (bDest == null) return nlen; int nCopied = nLength; if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart; if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset; if (nCopied > 0) { IntPtr ptr = UnsafeNativeMethods.sqlite3_column_blob(stmt._sqlite_stmt, index); Marshal.Copy((IntPtr)(ptr.ToInt64() + nDataOffset), bDest, nStart, nCopied); } else { nCopied = 0; } return nCopied; }
internal override int ColumnCount(SQLiteStatement stmt) { return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt); }
internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt) { switch (_datetimeFormat) { case SQLiteDateFormats.Ticks: case SQLiteDateFormats.JulianDay: case SQLiteDateFormats.UnixEpoch: { base.Bind_DateTime(stmt, flags, index, dt); break; } default: { #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { SQLiteStatementHandle handle = (stmt != null) ? stmt._sqlite_stmt : null; LogBind(handle, index, dt); } #endif Bind_Text(stmt, flags, index, ToString(dt)); break; } } }
internal override long GetChars(SQLiteStatement stmt, int index, int nDataOffset, char[] bDest, int nStart, int nLength) { int nlen; int nCopied = nLength; string str = GetText(stmt, index); nlen = str.Length; if (bDest == null) return nlen; if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart; if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset; if (nCopied > 0) str.CopyTo(nDataOffset, bDest, nStart, nCopied); else nCopied = 0; return nCopied; }
internal override DateTime GetDateTime(SQLiteStatement stmt, int index) { if (_datetimeFormat == SQLiteDateFormats.Ticks) return ToDateTime(GetInt64(stmt, index), _datetimeKind); else if (_datetimeFormat == SQLiteDateFormats.JulianDay) return ToDateTime(GetDouble(stmt, index), _datetimeKind); else if (_datetimeFormat == SQLiteDateFormats.UnixEpoch) return ToDateTime(GetInt32(stmt, index), _datetimeKind); return ToDateTime(GetText(stmt, index)); }
internal override bool IsNull(SQLiteStatement stmt, int index) { return (ColumnAffinity(stmt, index) == TypeAffinity.Null); }
internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len); #else return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16(stmt._sqlite_stmt, index), UnsafeNativeMethods.sqlite3_column_bytes16(stmt._sqlite_stmt, index)); #endif }
/// <summary> /// Helper function to retrieve a column of data from an active statement. /// </summary> /// <param name="stmt">The statement being step()'d through</param> /// <param name="flags">The flags associated with the connection.</param> /// <param name="index">The column index to retrieve</param> /// <param name="typ">The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information.</param> /// <returns>Returns the data in the column</returns> internal override object GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, SQLiteType typ) { TypeAffinity aff = typ.Affinity; if (aff == TypeAffinity.Null) return DBNull.Value; Type t = null; if (typ.Type != DbType.Object) { t = SQLiteConvert.SQLiteTypeToType(typ); aff = TypeToAffinity(t); } if ((flags & SQLiteConnectionFlags.GetAllAsText) == SQLiteConnectionFlags.GetAllAsText) return GetText(stmt, index); switch (aff) { case TypeAffinity.Blob: if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text) return new Guid(GetText(stmt, index)); int n = (int)GetBytes(stmt, index, 0, null, 0, 0); byte[] b = new byte[n]; GetBytes(stmt, index, 0, b, 0, n); if (typ.Type == DbType.Guid && n == 16) return new Guid(b); return b; case TypeAffinity.DateTime: return GetDateTime(stmt, index); case TypeAffinity.Double: if (t == null) return GetDouble(stmt, index); return Convert.ChangeType(GetDouble(stmt, index), t, null); case TypeAffinity.Int64: if (t == null) return GetInt64(stmt, index); if (t == typeof(SByte)) return GetSByte(stmt, index); if (t == typeof(Byte)) return GetByte(stmt, index); if (t == typeof(Int16)) return GetInt16(stmt, index); if (t == typeof(UInt16)) return GetUInt16(stmt, index); if (t == typeof(Int32)) return GetInt32(stmt, index); if (t == typeof(UInt32)) return GetUInt32(stmt, index); if (t == typeof(UInt64)) return GetUInt64(stmt, index); return Convert.ChangeType(GetInt64(stmt, index), t, null); default: return GetText(stmt, index); } }
internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage) { #if !SQLITE_STANDARD return UnsafeNativeMethods.sqlite3_table_cursor_interop(stmt._sqlite_stmt, db, rootPage); #else return -1; #endif }
internal override long GetRowIdForCursor(SQLiteStatement stmt, int cursor) { #if !SQLITE_STANDARD long rowid; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_cursor_rowid_interop(stmt._sqlite_stmt, cursor, out rowid); if (rc == SQLiteErrorCode.Ok) return rowid; return 0; #else return 0; #endif }
/// <summary> /// This function attempts to map all parameters in the collection to all statements in a Command. /// Since named parameters may span multiple statements, this function makes sure all statements are bound /// to the same named parameter. Unnamed parameters are bound in sequence. /// </summary> internal void MapParameters(SQLiteStatement activeStatement) { if (_unboundFlag == false || _parameterList.Count == 0 || _command._statementList == null) { return; } int nUnnamed = 0; string s; int n; int y = -1; SQLiteStatement stmt; foreach (SQLiteParameter p in _parameterList) { y++; s = p.ParameterName; if (s == null) { s = String.Format(CultureInfo.InvariantCulture, ";{0}", nUnnamed); nUnnamed++; } int x; bool isMapped = false; if (activeStatement == null) { x = _command._statementList.Count; } else { x = 1; } stmt = activeStatement; for (n = 0; n < x; n++) { isMapped = false; if (stmt == null) { stmt = _command._statementList[n]; } if (stmt._paramNames != null) { if (stmt.MapParameter(s, p) == true) { isMapped = true; } } stmt = null; } // If the parameter has a name, but the SQL statement uses unnamed references, this can happen -- attempt to map // the parameter by its index in the collection if (isMapped == false) { s = String.Format(CultureInfo.InvariantCulture, ";{0}", y); stmt = activeStatement; for (n = 0; n < x; n++) { if (stmt == null) { stmt = _command._statementList[n]; } if (stmt._paramNames != null) { if (stmt.MapParameter(s, p) == true) { isMapped = true; } } stmt = null; } } } if (activeStatement == null) { _unboundFlag = false; } }
internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle); if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Statement {0} paramter count is {1}.", handleIntPtr, value)); } return value; }