示例#1
0
        /// <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();
                }
            });
        }
示例#3
0
        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();
                }
            });
        }
示例#6
0
        /// <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);
        }
示例#7
0
        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());
        }
示例#9
0
//        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;
        }
示例#10
0
        /// <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;
        }
示例#14
0
        /// <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);
        }