/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor RawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadRequest, TAG, "RawQuery called on closed database"); } Cursor cursor = null; sqlite3_stmt command = null; var t = Factory.StartNew(() => { try { Log.To.Database.V(TAG, "RawQuery sql: {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray())); command = BuildCommand(_readConnection, sql, paramArgs); cursor = new Cursor(command); } catch (Exception e) { if (command != null) { command.Dispose(); } var args = new SecureLogJsonString(paramArgs, LogMessageSensitivity.PotentiallyInsecure); Log.To.Database.E(TAG, String.Format("Error executing raw query '{0}' with values '{1}', rethrowing...", sql, paramArgs == null ? (object)String.Empty : new SecureLogJsonString(args, LogMessageSensitivity.PotentiallyInsecure)), e); LastErrorCode = raw.sqlite3_errcode(_readConnection); throw; } return(cursor); }); return(t.Result); }
public void SetVersion(Int32 version) { var errMessage = "Unable to set version to {0}".Fmt(version); var commandText = "PRAGMA user_version = ?"; Factory.StartNew(() => { sqlite3_stmt statement = _writeConnection.prepare(commandText); if (raw.sqlite3_bind_int(statement, 1, version) == raw.SQLITE_ERROR) { throw new CouchbaseLiteException(errMessage, StatusCode.DbError); } int result; try { result = statement.step(); if (result != SQLiteResult.OK) { throw new CouchbaseLiteException(errMessage, StatusCode.DbError); } } catch (Exception e) { Log.E(Tag, "Error getting user version", e); } finally { statement.Dispose(); } }); }
public void SetVersion(int version) { if (_readOnly) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.Forbidden, TAG, "Attempting to write to a readonly database"); } const string commandText = "PRAGMA user_version = ?"; Factory.StartNew(() => { sqlite3_stmt statement = BuildCommand(_writeConnection, commandText, null); if ((LastErrorCode = raw.sqlite3_bind_int(statement, 1, version)) == raw.SQLITE_ERROR) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.DbError, TAG, "Unable to set version to {0} ({1})", version, LastErrorCode); } try { LastErrorCode = statement.step(); if (LastErrorCode != raw.SQLITE_OK) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.DbError, TAG, "Unable to set version to {0} ({1})", version, LastErrorCode); } } catch (Exception e) { Log.To.Database.W(TAG, "Error getting user version, recording error...", e); LastErrorCode = raw.sqlite3_errcode(_writeConnection); } finally { statement.Dispose(); } }); }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor RawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { Open(Path); } Cursor cursor = null; sqlite3_stmt command = null; var t = Factory.StartNew(() => { try { Log.V(Tag, "RawQuery sql: {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray())); command = BuildCommand(_readConnection, sql, paramArgs); cursor = new Cursor(command); } catch (Exception e) { if (command != null) { command.Dispose(); } var args = paramArgs == null ? String.Empty : String.Join(",", paramArgs.ToStringArray()); Log.E(Tag, "Error executing raw query '{0}' is values '{1}' {2}".Fmt(sql, args, _readConnection.errmsg()), e); throw; } return(cursor); }); return(t.Result); }
public void SetVersion(int version) { var errMessage = "Unable to set version to {0}".Fmt(version); const string commandText = "PRAGMA user_version = ?"; Factory.StartNew(() => { sqlite3_stmt statement = BuildCommand(_writeConnection, commandText, null); if ((LastErrorCode = raw.sqlite3_bind_int(statement, 1, version)) == raw.SQLITE_ERROR) { throw new CouchbaseLiteException(errMessage, StatusCode.DbError); } try { LastErrorCode = statement.step(); if (LastErrorCode != SQLiteResult.OK) { throw new CouchbaseLiteException(errMessage, StatusCode.DbError); } } catch (Exception e) { Log.E(TAG, "Error getting user version", e); LastErrorCode = raw.sqlite3_errcode(_writeConnection); } finally { statement.Dispose(); } }); }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor RawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { throw new CouchbaseLiteException("RawQuery called on closed database", StatusCode.BadRequest); } Cursor cursor = null; sqlite3_stmt command = null; var t = Factory.StartNew(() => { try { Log.V(TAG, "RawQuery sql: {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray())); command = BuildCommand(_readConnection, sql, paramArgs); cursor = new Cursor(command); } catch (Exception e) { if (command != null) { command.Dispose(); } var args = paramArgs == null ? String.Empty : String.Join(",", paramArgs.ToStringArray()); Log.E(TAG, "Error executing raw query '{0}' is values '{1}' {2}".Fmt(sql, args, _readConnection.errmsg()), e); LastErrorCode = raw.sqlite3_errcode(_readConnection); throw; } return(cursor); }); return(t.Result); }
private int ExecSQL(string sql, sqlite3 db, params object[] paramArgs) { Log.To.TaskScheduling.V(TAG, "Scheduling ExecSQL"); var t = Factory.StartNew(() => { Log.To.TaskScheduling.V(TAG, "Running ExecSQL"); sqlite3_stmt command = null; try { command = BuildCommand(db, sql, paramArgs); LastErrorCode = command.step(); if (LastErrorCode == raw.SQLITE_ERROR) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.DbError, TAG, "SQLite error in ExecSQL: {0}", raw.sqlite3_errmsg(db)); } } catch (ugly.sqlite3_exception e) { Log.To.Database.E(TAG, String.Format("Error {0}, {1} ({2}) executing sql '{3}'", e.errcode, db.extended_errcode(), raw.sqlite3_errmsg(db), sql), e); LastErrorCode = e.errcode; throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.DbError, TAG, "Error {0}, {1} ({2}) executing sql '{3}'", e.errcode, db.extended_errcode(), raw.sqlite3_errmsg(db), sql); } finally { if (command != null) { command.Dispose(); } } }, _cts.Token); try { //FIXME.JHB: This wait should be optional (API change) t.Wait(30000, _cts.Token); } catch (AggregateException ex) { throw ex.InnerException; } catch (OperationCanceledException) { //Closing the storage engine will cause the factory to stop processing, but still //accept new jobs into the scheduler. If execution has gotten here, it means that //ExecSQL was called after Close, and the job will be ignored. Might consider //subclassing the factory to avoid this awkward behavior Log.To.Database.I(TAG, "StorageEngine closed, canceling operation"); return(0); } if (t.Status != TaskStatus.RanToCompletion) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InternalServerError, TAG, "ExecSQL timed out waiting for Task #{0}", t.Id); } return(db.changes()); }
/// <summary> /// Execute any SQL that changes the database. /// </summary> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public int ExecSQL(String sql, params Object[] paramArgs) { var t = Factory.StartNew(() => { sqlite3_stmt command = null; try { command = BuildCommand(_writeConnection, sql, paramArgs); var result = command.step(); if (result == SQLiteResult.ERROR) { throw new CouchbaseLiteException(raw.sqlite3_errmsg(_writeConnection), StatusCode.DbError); } } catch (ugly.sqlite3_exception e) { Log.E(Tag, "Error {0}, {1} executing sql '{2}'".Fmt(e.errcode, _writeConnection.extended_errcode(), sql), e); throw; } finally { if (command != null) { command.Dispose(); } } }, _cts.Token); try { //FIXME.JHB: This wait should be optional (API change) t.Wait(30000, _cts.Token); } catch (AggregateException ex) { throw ex.InnerException; } catch (OperationCanceledException) { //Closing the storage engine will cause the factory to stop processing, but still //accept new jobs into the scheduler. If execution has gotten here, it means that //ExecSQL was called after Close, and the job will be ignored. Might consider //subclassing the factory to avoid this awkward behavior Log.D(Tag, "StorageEngine closed, canceling operation"); return(0); } if (t.Status != TaskStatus.RanToCompletion) { Log.E(Tag, "ExecSQL timed out waiting for Task #{0}", t.Id); throw new CouchbaseLiteException("ExecSQL timed out", StatusCode.InternalServerError); } return(_writeConnection.changes()); }
// public byte[] GetBlob (int columnIndex, int chunkSize) // { // SQLitePCL.SQLiteConnection // // var result = statement[columnIndex]; // if (result == null) return new byte[2]; // NOTE.ZJG: Database.AppendDictToJSON assumes an empty json doc has a for a length of two. // var r = statement; // // var chunkBuffer = new byte[chunkSize]; // var blob = new List<Byte>(chunkSize); // We know we'll be reading at least 1 chunk, so pre-allocate now to avoid an immediate resize. // // long bytesRead; // do // { // chunkBuffer.Initialize(); // Resets all values back to zero. // bytesRead = r[columnIndex](columnIndex, blob.Count, chunkBuffer, 0, chunkSize); // blob.AddRange(chunkBuffer.Take(Convert.ToInt32(bytesRead))); // } while (bytesRead > 0); // // return blob.ToArray(); // } public void Close() { if (statement == null) { return; } statement.Dispose(); statement = null; }
/// <summary> /// Releases all resource used by the <see cref="Couchbase.Lite.Cursor"/> object. /// </summary> /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="Couchbase.Lite.Cursor"/>. The /// <see cref="Dispose"/> method leaves the <see cref="Couchbase.Lite.Cursor"/> in an unusable state. After /// calling <see cref="Dispose"/>, you must release all references to the <see cref="Couchbase.Lite.Cursor"/> so /// the garbage collector can reclaim the memory that the <see cref="Couchbase.Lite.Cursor"/> was occupying.</remarks> public void Dispose() { if (_statement == null) { return; } lock (StmtDisposeLock) { _statement.Dispose(); _statement = null; } }
static void Close(ref sqlite3 db) { if (db == null) { return; } var dbCopy = db; db = null; try { // Close any open statements, otherwise the // sqlite connection won't actually close. sqlite3_stmt next = null; while ((next = dbCopy.next_stmt(next)) != null) { next.Dispose(); } dbCopy.close(); Log.I(TAG, "db connection {0} closed", dbCopy); } catch (KeyNotFoundException ex) { // Appears to be a bug in sqlite3.find_stmt. Concurrency issue in static dictionary? // Assuming we're done. Log.W(TAG, "Abandoning database close.", ex); } catch (ugly.sqlite3_exception ex) { Log.E(TAG, "Retrying database close.", ex); // Assuming a basic retry fixes this. Thread.Sleep(5000); dbCopy.close(); } GC.Collect(); GC.WaitForPendingFinalizers(); try { dbCopy.Dispose(); } catch (Exception ex) { Log.E(TAG, "Error while closing database.", ex); } }
public int Update(String table, ContentValues values, String whereClause, params String[] whereArgs) { Debug.Assert(!String.IsNullOrWhiteSpace(table)); Debug.Assert(values != null); var command = GetUpdateCommand(table, values, whereClause, whereArgs); sqlite3_stmt lastInsertedIndexCommand = null; var resultCount = -1; try { var result = command.Step(); if (result == SQLiteResult.ERROR) { throw new CouchbaseLiteException(command.Connection.ErrorMessage(), StatusCode.DbError); } // Get the new row's id. // TODO.ZJG: This query should ultimately be replaced with a call to sqlite3_last_insert_rowid. lastInsertedIndexCommand = Connection.Prepare("select changes()"); result = lastInsertedIndexCommand.Step(); if (result != SQLiteResult.ERROR) { throw new CouchbaseLiteException(lastInsertedIndexCommand.Connection.ErrorMessage(), StatusCode.DbError); } resultCount = Convert.ToInt32(lastInsertedIndexCommand[0]); if (resultCount == -1) { throw new CouchbaseLiteException("Failed to update any records.", StatusCode.DbError); } } catch (Exception ex) { Log.E(Tag, "Error updating table " + table, ex); } finally { command.Dispose(); if (lastInsertedIndexCommand != null) { lastInsertedIndexCommand.Dispose(); } } return(resultCount); }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor RawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadRequest, TAG, "RawQuery called on closed database"); } Cursor cursor = null; sqlite3_stmt command = null; var connection = default(Connection); //Log.To.TaskScheduling.V(TAG, "Scheduling RawQuery"); //var t = Factory.StartNew (() => //{ Log.To.TaskScheduling.V(TAG, "Running RawQuery"); try { connection = IsOnDBThread ? new Connection(_writeConnection, null) : _readerConnections.Acquire(); Log.To.Database.V(TAG, "RawQuery sql ({2}): {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray()), IsOnDBThread ? "read uncommit" : "read commit"); command = BuildCommand(connection.Raw, sql, paramArgs); cursor = new Cursor(command, connection); } catch (Exception e) { if (command != null) { command.Dispose(); } var args = new SecureLogJsonString(paramArgs, LogMessageSensitivity.PotentiallyInsecure); Log.To.Database.E(TAG, String.Format("Error executing raw query '{0}' with values '{1}', rethrowing...", sql, paramArgs == null ? (object)String.Empty : new SecureLogJsonString(args, LogMessageSensitivity.PotentiallyInsecure)), e); LastErrorCode = raw.sqlite3_errcode(connection.Raw); throw; } return(cursor); //}); //return t.Result; }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor IntransactionRawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadRequest, TAG, "IntransactionRawQuery called on closed database"); } if (transactionCount == 0) { return(RawQuery(sql, paramArgs)); } Log.To.TaskScheduling.V(TAG, "Scheduling InTransactionRawQuery"); var t = Factory.StartNew(() => { Log.To.TaskScheduling.V(TAG, "Running InTransactionRawQuery"); Cursor cursor = null; sqlite3_stmt command = null; try { Log.To.Database.V(TAG, "RawQuery sql: {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray())); command = BuildCommand(_writeConnection, sql, paramArgs); cursor = new Cursor(command); } catch (Exception e) { if (command != null) { command.Dispose(); } Log.To.Database.E(TAG, String.Format("Error executing raw query '{0}', rethrowing...", sql), e); LastErrorCode = raw.sqlite3_errcode(_writeConnection); throw; } return(cursor); }); return(t.Result); }
static void Close(ref sqlite3 db) { var dbCopy = Interlocked.Exchange(ref db, null); if (dbCopy == null) { return; } try { // Close any open statements, otherwise the // sqlite connection won't actually close. sqlite3_stmt next = null; while ((next = dbCopy.next_stmt(next)) != null) { next.Dispose(); } dbCopy.close(); } catch (KeyNotFoundException ex) { // Appears to be a bug in sqlite3.find_stmt. Concurrency issue in static dictionary? // Assuming we're done. Log.To.Database.W(TAG, "Abandoning database close.", ex); } catch (ugly.sqlite3_exception ex) { Log.To.Database.I(TAG, "Retrying database close due to exception.", ex); // Assuming a basic retry fixes this. Thread.Sleep(5000); dbCopy.close(); } try { dbCopy.Dispose(); } catch (Exception ex) { Log.To.Database.W(TAG, "Error while closing database, continuing...", ex); } }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor IntransactionRawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { Open(Path); } if (transactionCount == 0) { return(RawQuery(sql, paramArgs)); } var t = Factory.StartNew(() => { Cursor cursor = null; sqlite3_stmt command = null; try { Log.V(TAG, "RawQuery sql: {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray())); command = BuildCommand(_writeConnection, sql, paramArgs); cursor = new Cursor(command); } catch (Exception e) { if (command != null) { command.Dispose(); } Log.E(TAG, "Error executing raw query '{0}'".Fmt(sql), e); LastErrorCode = raw.sqlite3_errcode(_writeConnection); throw; } return(cursor); }); return(t.Result); }