示例#1
0
        public void test_stmt_busy()
        {
            using (sqlite3 db = ugly.open(":memory:"))
            {
                db.exec("CREATE TABLE foo (x int);");
                db.exec("INSERT INTO foo (x) VALUES (1);");
                db.exec("INSERT INTO foo (x) VALUES (2);");
                db.exec("INSERT INTO foo (x) VALUES (3);");
                const string sql = "SELECT x FROM foo";
                using (sqlite3_stmt stmt = db.prepare(sql))
                {
                    Assert.AreEqual(sql, stmt.sql());

                    Assert.AreEqual(stmt.stmt_busy(), 0);
                    stmt.step();
                    Assert.IsTrue(stmt.stmt_busy() != 0);
                    stmt.step();
                    Assert.IsTrue(stmt.stmt_busy() != 0);
                    stmt.step();
                    Assert.IsTrue(stmt.stmt_busy() != 0);
                    stmt.step();
                    Assert.IsTrue(stmt.stmt_busy() == 0);
                }
            }
        }
示例#2
0
 // allows only one statement in the sql string
 public static void exec(this sqlite3 db, string sql, params object[] a)
 {
     using (sqlite3_stmt stmt = db.prepare(sql, a))
     {
         stmt.step();
     }
 }
        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();
                }
            });
        }
示例#4
0
 internal Cursor(sqlite3_stmt stmt, object dbLock)
 {
     this.dbLock    = dbLock;
     this.statement = stmt;
     currentRow     = -1;
     lock (dbLock) { currentStep = statement.step(); }
 }
示例#5
0
        public void test_column_origin()
        {
            using (sqlite3 db = ugly.open(":memory:"))
            {
                db.exec("CREATE TABLE foo (x int, v int, t text, d real, b blob, q blob);");
                byte[] blob = db.query_scalar <byte[]>("SELECT randomblob(5);");
                db.exec("INSERT INTO foo (x,v,t,d,b,q) VALUES (?,?,?,?,?,?)", 32, 44, "hello", 3.14, blob, null);
#if not
                // maybe we should just let this fail so we can
                // see the differences between running against the built-in
                // sqlite vs a recent version?
                if (1 == raw.sqlite3_compileoption_used("ENABLE_COLUMN_METADATA"))
#endif
                {
                    using (sqlite3_stmt stmt = db.prepare("SELECT x AS mario FROM foo;"))
                    {
                        stmt.step();

                        Assert.IsTrue(stmt.stmt_readonly() != 0);

                        Assert.AreEqual(stmt.column_database_name(0), "main");
                        Assert.AreEqual(stmt.column_table_name(0), "foo");
                        Assert.AreEqual(stmt.column_origin_name(0), "x");
                        Assert.AreEqual(stmt.column_name(0), "mario");
                        Assert.AreEqual(stmt.column_decltype(0), "int");
                    }
                }
            }
        }
        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();
                }
            });
        }
示例#7
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();
                }
            });
        }
示例#8
0
 public static T query_scalar <T>(this sqlite3 db, string sql, params object[] a)
 {
     using (sqlite3_stmt stmt = db.prepare(sql, a))
     {
         stmt.step();
         return(stmt.column <T>(0));
     }
 }
示例#9
0
 public static void step_done(this sqlite3_stmt stmt)
 {
     int rc = stmt.step();
     if (rc != raw.SQLITE_DONE)
     {
         throw new sqlite3_exception(rc, "expected SQLITE_DONE");
     }
 }
示例#10
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());
        }
示例#12
0
 public static IEnumerable <T> query <T> (this sqlite3 db, string sql, params object[] a) where T : class, new()
 {
     using (sqlite3_stmt stmt = db.prepare(sql, a))
     {
         while (raw.SQLITE_ROW == stmt.step())
         {
             yield return(stmt.row <T>());
         }
     }
 }
示例#13
0
        //NOTE.JHB: Can throw an exception
        internal Cursor(sqlite3_stmt stmt)
        {
            this._statement = stmt;
            _currentRow     = -1;
            _currentStep    = _statement.step();

            if (_currentStep != raw.SQLITE_OK && _currentStep != raw.SQLITE_ROW && _currentStep != raw.SQLITE_DONE)
            {
                Log.E("Cursor", "currentStep: " + _currentStep);
            }
        }
示例#14
0
        public bool MoveToNext()
        {
            if (currentRow >= 0)
            {
                currentStep = statement.step();
            }

            if (HasRows)
            {
                currentRow++;
            }
            return(HasRows);
        }
示例#15
0
        public void test_row()
        {
            using (sqlite3 db = ugly.open(":memory:"))
            {
                db.exec("CREATE TABLE foo (x int, v int, t text, d real, b blob, q blob);");
                byte[] blob = db.query_scalar <byte[]>("SELECT randomblob(5);");
                db.exec("INSERT INTO foo (x,v,t,d,b,q) VALUES (?,?,?,?,?,?)", 32, 44, "hello", 3.14, blob, null);
                foreach (row r in db.query <row>("SELECT x,v,t,d,b,q FROM foo;"))
                {
                    Assert.AreEqual(r.x, 32);
                    Assert.AreEqual(r.v, 44);
                    Assert.AreEqual(r.t, "hello");
                    Assert.AreEqual(r.d, 3.14);
                    Assert.AreEqual(r.b.Length, blob.Length);
                    for (int i = 0; i < blob.Length; i++)
                    {
                        Assert.AreEqual(r.b[i], blob[i]);
                    }
                    Assert.AreEqual(r.q, null);
                }
                using (sqlite3_stmt stmt = db.prepare("SELECT x,v,t,d,b,q FROM foo;"))
                {
                    stmt.step();

                    Assert.AreEqual(stmt.db_handle(), db);

                    Assert.AreEqual(stmt.column_int(0), 32);
                    Assert.AreEqual(stmt.column_int64(1), 44);
                    Assert.AreEqual(stmt.column_text(2), "hello");
                    Assert.AreEqual(stmt.column_double(3), 3.14);
                    Assert.AreEqual(stmt.column_bytes(4), blob.Length);
                    byte[] b2 = stmt.column_blob(4);
                    Assert.AreEqual(b2.Length, blob.Length);
                    for (int i = 0; i < blob.Length; i++)
                    {
                        Assert.AreEqual(b2[i], blob[i]);
                    }

                    Assert.AreEqual(stmt.column_type(5), raw.SQLITE_NULL);

                    Assert.AreEqual(stmt.column_name(0), "x");
                    Assert.AreEqual(stmt.column_name(1), "v");
                    Assert.AreEqual(stmt.column_name(2), "t");
                    Assert.AreEqual(stmt.column_name(3), "d");
                    Assert.AreEqual(stmt.column_name(4), "b");
                    Assert.AreEqual(stmt.column_name(5), "q");
                }
            }
        }
示例#16
0
        public static IEnumerable <T> query_one_column <T> (this sqlite3 db, string sql, params object[] a)
        {
            using (sqlite3_stmt stmt = db.prepare(sql, a))
            {
                if (1 != stmt.column_count())
                {
                    throw new InvalidOperationException("the SELECT expression for query_one_column() must have exactly one column");
                }

                while (raw.SQLITE_ROW == stmt.step())
                {
                    yield return(stmt.column <T>(0));
                }
            }
        }
        private bool Step()
        {
            int rc = _stmt.step();

            if (raw.SQLITE_ROW == rc)
            {
                _cur++;
                return(true);
            }
            // TODO we've reached the end.  we should notify somebody.

            _done = true;

            return(false);
        }
示例#18
0
        public void test_progress_handler()
        {
            using (sqlite3 db = ugly.open(":memory:"))
            {
                int count = 0;

                delegate_progress_handler handler = obj =>
                {
                    Assert.AreEqual(obj, "user_data");
                    count++;
                    return(0);
                };

                raw.sqlite3_progress_handler(db, 1, handler, "user_data");

                GC.Collect();

                using (sqlite3_stmt stmt = db.prepare("SELECT 1;"))
                {
                    stmt.step();
                }
                Assert.IsTrue(count > 0);

                handler = obj => 1;
                raw.sqlite3_progress_handler(db, 1, handler, null);
                using (sqlite3_stmt stmt = db.prepare("SELECT 1;"))
                {
                    try
                    {
                        stmt.step();
                        Assert.Fail("Expected sqlite3_exception");
                    }
                    catch (ugly.sqlite3_exception e)
                    {
                        Assert.AreEqual(e.errcode, raw.SQLITE_INTERRUPT);
                    }
                }

                // Test that assigning null to the handler removes the progress handler.
                handler = null;
                raw.sqlite3_progress_handler(db, 1, handler, null);
                using (sqlite3_stmt stmt = db.prepare("SELECT 1;"))
                {
                    stmt.step();
                }
            }
        }
示例#19
0
        /// <summary>
        /// Moves to the next result in the set
        /// </summary>
        /// <returns><c>true</c>, if the cursor was able to move, <c>false</c> otherwise.</returns>
        public bool MoveToNext()
        {
            if (_currentRow >= 0)
            {
                _currentStep = _statement.step();

                if (_currentStep != raw.SQLITE_OK && _currentStep != raw.SQLITE_ROW && _currentStep != raw.SQLITE_DONE)
                {
                    Log.To.Database.W("Cursor", "Couldn't move to next value ({0})", _currentStep);
                }
            }

            if (HasRows)
            {
                _currentRow++;
            }
            return(HasRows);
        }
        /// <summary>
        /// Moves to the next result in the set
        /// </summary>
        /// <returns><c>true</c>, if the cursor was able to move, <c>false</c> otherwise.</returns>
        public bool MoveToNext()
        {
            if (_currentRow >= 0)
            {
                _currentStep = _statement.step();

                if (_currentStep != raw.SQLITE_OK && _currentStep != raw.SQLITE_ROW && _currentStep != raw.SQLITE_DONE)
                {
                    Log.E("Cursor", "currentStep: " + _currentStep);
                }
            }

            if (HasRows)
            {
                _currentRow++;
            }
            return(HasRows);
        }
示例#21
0
 public void test_explicit_prepare()
 {
     using (sqlite3 db = ugly.open(":memory:"))
     {
         db.exec("CREATE TABLE foo (x int);");
         const int num = 7;
         using (sqlite3_stmt stmt = db.prepare("INSERT INTO foo (x) VALUES (?)"))
         {
             for (int i = 0; i < num; i++)
             {
                 stmt.reset();
                 stmt.clear_bindings();
                 stmt.bind(1, i);
                 stmt.step();
             }
         }
         int c = db.query_scalar <int>("SELECT COUNT(*) FROM foo");
         Assert.AreEqual(c, num);
     }
 }
        // this implementation of a sqlite rowlist is only appropriate if there is
        // a bind parameter which will return a result for every row.  unless you
        // don't mind empty rows in the grid, gaps where nothing is displayed.
        // however, this will be much faster than the IEnumish one, and doesn't
        // require a cache in front of it.

        public bool get_value(int row, out TRow val)
        {
            // TODO or should the reset be done AFTER?
            _stmt.reset();

            _stmt.clear_bindings();              // TODO probably not safe to clear bindings here because we only own one of them

            _stmt.bind_int(1, row);              // TODO the ndx of the bind param should be a param to the constructor of this class

            int rc = _stmt.step();

            if (raw.SQLITE_ROW != rc)
            {
                val = default(TRow);
                return(false);
            }

            val = get_row();
            return(true);
        }
示例#23
0
        public void test_blob_write()
        {
            using (sqlite3 db = ugly.open(":memory:"))
            {
                const int len = 100;

                db.exec("CREATE TABLE foo (b blob);");
                using (sqlite3_stmt stmt = db.prepare("INSERT INTO foo (b) VALUES (?)"))
                {
                    stmt.bind_zeroblob(1, len);
                    stmt.step();
                }

                long rowid = db.last_insert_rowid();

                using (sqlite3_blob bh = db.blob_open("main", "foo", "b", rowid, 1))
                {
                    int len2 = bh.bytes();
                    Assert.AreEqual(len, len2);

                    int passes = 10;

                    Assert.AreEqual(len % passes, 0);

                    int    sublen = len / passes;
                    byte[] buf    = new byte[sublen];
                    for (int i = 0; i < sublen; i++)
                    {
                        buf[i] = (byte)(i % 256);
                    }

                    for (int q = 0; q < passes; q++)
                    {
                        bh.write(buf, q * sublen);
                    }
                }
            }
        }
示例#24
0
 /// <summary>
 /// Can throw an exception
 /// </summary>
 /// <param name="stmt">Statement.</param>
 internal Cursor(sqlite3_stmt stmt)
 {
     this.statement = stmt;
     currentRow     = -1;
     currentStep    = statement.step();
 }