示例#1
0
 private void SetRows(QueryEnumerator queryEnumerator)
 {
     lock (this)
     {
         rows = queryEnumerator;
     }
 }
示例#2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="queryEnumerator">The base query enumerator.</param>
        /// <param name="postFilter">The post row folder or <c>null</c>.</param>
        internal EntityQueryEnumerator(QueryEnumerator queryEnumerator, Func <EntityQueryRow <TEntity>, bool> postFilter)
        {
            Covenant.Requires <ArgumentNullException>(queryEnumerator != null);

            this.Base       = queryEnumerator;
            this.postFilter = postFilter;
        }
示例#3
0
 public void Completed(QueryEnumerator rowsParam, Exception error)
 {
     if (error != null)
     {
         foreach (LiveQuery.ChangeListener observer in this._enclosing.observers)
         {
             observer.Changed(new LiveQuery.ChangeEvent(error));
         }
         this._enclosing.lastError = error;
     }
     else
     {
         if (this._enclosing.runningState.Get() == false)
         {
             Log.D(Log.TagQuery, "%s: update() finished query, but running state == false.", this
                   );
             return;
         }
         if (rowsParam != null && !rowsParam.Equals(this._enclosing.rows))
         {
             this._enclosing.SetRows(rowsParam);
             foreach (LiveQuery.ChangeListener observer in this._enclosing.observers)
             {
                 Log.D(Log.TagQuery, "%s: update() calling back observer with rows", this._enclosing
                       );
                 observer.Changed(new LiveQuery.ChangeEvent(this._enclosing, this._enclosing.rows)
                                  );
             }
         }
         this._enclosing.lastError = null;
     }
 }
        /// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
        public virtual void TestDeleteDocument()
        {
            Document document = database.CreateDocument();
            IDictionary <string, object> properties = new Dictionary <string, object>();

            properties.Put("foo", "foo");
            properties.Put("bar", false);
            document.PutProperties(properties);
            NUnit.Framework.Assert.IsNotNull(document.GetCurrentRevision());
            string docId = document.GetId();

            document.Delete();
            NUnit.Framework.Assert.IsTrue(document.IsDeleted());
            Document fetchedDoc = database.GetExistingDocument(docId);

            NUnit.Framework.Assert.IsNull(fetchedDoc);
            // query all docs and make sure we don't see that document
            database.GetAllDocs(new QueryOptions());
            Query           queryAllDocs    = database.CreateAllDocumentsQuery();
            QueryEnumerator queryEnumerator = queryAllDocs.Run();

            for (IEnumerator <QueryRow> it = queryEnumerator; it.HasNext();)
            {
                QueryRow row = it.Next();
                NUnit.Framework.Assert.IsFalse(row.GetDocument().GetId().Equals(docId));
            }
        }
        public void TestDeleteDocument()
        {
            var document   = database.CreateDocument();
            var properties = new Dictionary <string, object>();

            properties["foo"] = "foo";
            properties["bar"] = false;
            document.PutProperties(properties);
            Assert.IsNotNull(document.CurrentRevision);

            var docId = document.Id;

            document.Delete();
            Assert.IsTrue(document.Deleted);
            Document fetchedDoc = database.GetExistingDocument(docId);

            Assert.IsNull(fetchedDoc);

            // query all docs and make sure we don't see that document
            Query           queryAllDocs    = database.CreateAllDocumentsQuery();
            QueryEnumerator queryEnumerator = queryAllDocs.Run();

            foreach (var row in queryEnumerator)
            {
                Assert.IsFalse(row.Document.Id.Equals(docId));
            }
        }
 public void Completed(QueryEnumerator rowsParam, Exception error)
 {
     if (error != null)
     {
         foreach (LiveQuery.ChangeListener observer in this._enclosing.observers)
         {
             observer.Changed(new LiveQuery.ChangeEvent(error));
         }
         this._enclosing.lastError = error;
     }
     else
     {
         if (rowsParam != null && !rowsParam.Equals(this._enclosing.rows))
         {
             this._enclosing.SetRows(rowsParam);
             foreach (LiveQuery.ChangeListener observer in this._enclosing.observers)
             {
                 Log.D(Database.Tag, this._enclosing + ": update() calling back observer with rows"
                       );
                 observer.Changed(new LiveQuery.ChangeEvent(this._enclosing, this._enclosing.rows)
                                  );
             }
         }
         this._enclosing.lastError = null;
     }
 }
示例#7
0
        private void UpdateFinished(Task <QueryEnumerator> runTask)
        {
            _isUpdatingAtSequence = 0;

            if (UpdateQueryTokenSource.IsCancellationRequested)
            {
                return;
            }

            UpdateQueryTask = null;
            if (_updateAgain)
            {
                Update();
            }

            if (runTask.Status != TaskStatus.RanToCompletion)
            {
                Log.To.Query.W(TAG, String.Format("Query Updated task did not run to completion ({0})", runTask.Status), runTask.Exception);
                return; // NOTE: Assuming that we don't want to lose rows we already retrieved.
            }

            _rows = runTask.Result; // NOTE: Should this be 'append' instead of 'replace' semantics? If append, use a concurrent collection.
            Log.To.Query.I(TAG, "{0} async operation finished", this);
            LastError = runTask.Exception;

            var evt = _changed;

            if (evt == null)
            {
                return; // No delegates were subscribed, so no work to be done.
            }
            var args = new QueryChangeEventArgs(this, _rows, LastError);

            evt(this, args);
        }
        /// <summary>
        /// Implements the updating of the <see cref="Rows"/> collection.
        /// </summary>
        private void Update()
        {
            Log.D(Database.Tag, this + ": update() called.");

            if (View == null)
            {
                throw new CouchbaseLiteException("Cannot start LiveQuery when view is null");
            }

            if (!runningState)
            {
                Log.D(Database.Tag, this + ": update() called, but running state == false.  Ignoring.");
                return;
            }

            if (UpdateQueryTask != null &&
                UpdateQueryTask.Status != TaskStatus.Canceled &&
                UpdateQueryTask.Status != TaskStatus.RanToCompletion)
            {
                Log.D(Database.Tag, this + ": already a query in flight, scheduling call to update() once it's done");
                if (ReRunUpdateQueryTask != null &&
                    ReRunUpdateQueryTask.Status != TaskStatus.Canceled &&
                    ReRunUpdateQueryTask.Status != TaskStatus.RanToCompletion)
                {
                    ReRunUpdateQueryTokenSource.Cancel();
                    Log.D(Database.Tag, this + ": cancelled rerun update query token source.");
                }

                ReRunUpdateQueryTokenSource = new CancellationTokenSource();
                Database.Manager.RunAsync(() => { RunUpdateAfterQueryFinishes(); }, ReRunUpdateQueryTokenSource.Token);

                Log.D(Database.Tag, this + ": RunUpdateAfterQueryFinishes() is fired.");

                return;
            }

            UpdateQueryTokenSource = new CancellationTokenSource();

            UpdateQueryTask = RunAsync(base.Run, UpdateQueryTokenSource.Token)
                              .ContinueWith(runTask =>
            {
                if (runTask.Status != TaskStatus.RanToCompletion)
                {
                    Log.W(String.Format("Query Updated task did not run to completion ({0})", runTask.Status), runTask.Exception);
                    return;         // NOTE: Assuming that we don't want to lose rows we already retrieved.
                }

                rows      = runTask.Result;    // NOTE: Should this be 'append' instead of 'replace' semantics? If append, use a concurrent collection.
                LastError = runTask.Exception;

                var evt = Changed;
                if (evt == null)
                {
                    return;         // No delegates were subscribed, so no work to be done.
                }
                var args = new QueryChangeEventArgs(this, rows, LastError);
                evt(this, args);
            });
        }
        internal QueryEnumerator(QueryEnumerator rows)
        {
            Database       = rows.Database;
            Rows           = rows.Rows;
            SequenceNumber = rows.SequenceNumber;

            Reset();
        }
示例#10
0
        //---------------------------------------------------------------------
        // IDisposable implementation

        /// <inheritdoc/>
        public void Dispose()
        {
            if (Base != null)
            {
                Base.Dispose();
                Base = null;
            }
        }
示例#11
0
 internal QueryEnumerator(QueryEnumerator rows)
 {
     Database       = rows.Database;
     _rows          = rows._rows;
     _count         = rows._count;
     _enumerator    = _rows.GetEnumerator();
     SequenceNumber = rows.SequenceNumber;
 }
        /// <summary>https://github.com/couchbase/couchbase-lite-android/issues/134</summary>
        /// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        public virtual void TestGetAttachmentBodyUsingPrefetch()
        {
            // add a doc with an attachment
            Document        doc = database.CreateDocument();
            UnsavedRevision rev = doc.CreateRevision();
            IDictionary <string, object> properties = new Dictionary <string, object>();

            properties["foo"] = "bar";
            rev.SetUserProperties(properties);
            byte[]     attachBodyBytes = Sharpen.Runtime.GetBytesForString("attach body");
            Attachment attachment      = new Attachment(new ByteArrayInputStream(attachBodyBytes),
                                                        "text/plain");
            string attachmentName = "test_attachment.txt";

            rev.AddAttachment(attachment, attachmentName);
            rev.Save();
            // do query that finds that doc with prefetch
            View view = database.GetView("aview");

            view.SetMapReduce((IDictionary <string, object> document, EmitDelegate emitter) =>
            {
                string id = (string)document["_id"];
                emitter.Emit(id, null);
            }, null, "1");
            // try to get the attachment
            Query query = view.CreateQuery();

            query.Prefetch = true;
            QueryEnumerator results = query.Run();

            while (results.MoveNext())
            {
                QueryRow row = results.Current;
                // This returns the revision just fine, but the sequence number
                // is set to 0.
                SavedRevision  revision    = row.Document.CurrentRevision;
                IList <string> attachments = revision.AttachmentNames;
                // This returns an Attachment object which looks ok, except again
                // its sequence number is 0. The metadata property knows about
                // the length and mime type of the attachment. It also says
                // "stub" -> "true".
                Attachment attachmentRetrieved = revision.GetAttachment(attachmentName);
                // This throws a CouchbaseLiteException with StatusCode.NOT_FOUND.
                InputStream @is = attachmentRetrieved.GetContent();
                NUnit.Framework.Assert.IsNotNull(@is);
                byte[] attachmentDataRetrieved       = TextUtils.Read(@is);
                string attachmentDataRetrievedString = Sharpen.Runtime.GetStringForBytes(attachmentDataRetrieved
                                                                                         );
                string attachBodyString = Sharpen.Runtime.GetStringForBytes(attachBodyBytes);
                NUnit.Framework.Assert.AreEqual(attachBodyString, attachmentDataRetrievedString);
            }
        }
 public override bool Equals(object o)
 {
     if (this == o)
     {
         return(true);
     }
     if (o == null || GetType() != o.GetType())
     {
         return(false);
     }
     Couchbase.Lite.QueryEnumerator that = (Couchbase.Lite.QueryEnumerator)o;
     if (rows != null ? !rows.Equals(that.rows) : that.rows != null)
     {
         return(false);
     }
     return(true);
 }
示例#14
0
        /// <summary>Sends the query to the server and returns an enumerator over the result rows (Synchronous).
        ///     </summary>
        /// <remarks>
        /// Sends the query to the server and returns an enumerator over the result rows (Synchronous).
        /// Note: In a CBLLiveQuery you should add a ChangeListener and call start() instead.
        /// </remarks>
        /// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
        public override QueryEnumerator Run()
        {
            while (true)
            {
                try {
                    if (UpdateQueryTask.Status != TaskStatus.Canceled || UpdateQueryTask.Status != TaskStatus.RanToCompletion)
                    {
                        Log.To.Query.W(TAG, "Run called white update query task still running.");
                    }
                    WaitForRows();
                    break;
                } catch (OperationCanceledException) { //TODO: Review
                    Log.To.Query.V(TAG, "Run() caught OperationCanceledException, retrying...");
                    continue;
                } catch (Exception e) {
                    LastError = e;
                    _rows     = null;
                    Log.To.Query.W(TAG, "Exception caught during Run(), returning null...", e);
                }
            }

            return(_rows == null ? null : new QueryEnumerator(_rows));
        }
示例#15
0
 public void Run()
 {
     try
     {
         if (!this._enclosing.GetDatabase().IsOpen())
         {
             throw new InvalidOperationException("The database has been closed.");
         }
         string           viewName    = this._enclosing.view.GetName();
         QueryOptions     options     = this._enclosing.GetQueryOptions();
         IList <long>     outSequence = new AList <long>();
         IList <QueryRow> rows        = this._enclosing.database.QueryViewNamed(viewName, options,
                                                                                outSequence);
         long            sequenceNumber = outSequence[0];
         QueryEnumerator enumerator     = new QueryEnumerator(this._enclosing.database, rows,
                                                              sequenceNumber);
         onComplete.Completed(enumerator, null);
     }
     catch (Exception t)
     {
         onComplete.Completed(null, t);
     }
 }
示例#16
0
 internal ChangeEvent(LiveQuery source, QueryEnumerator queryEnumerator)
 {
     this.source          = source;
     this.queryEnumerator = queryEnumerator;
 }
 internal QueryEnumerator(Couchbase.Lite.QueryEnumerator other)
 {
     this.database       = other.database;
     this.rows           = other.rows;
     this.sequenceNumber = other.sequenceNumber;
 }
示例#18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Couchbase.Lite.QueryCompletedEventArgs"/> class.
 /// </summary>
 /// <param name="rows">Rows.</param>
 /// <param name="errorInfo">Error info.</param>
 public QueryCompletedEventArgs(QueryEnumerator rows, Exception errorInfo)
 {
     Rows      = rows;
     ErrorInfo = errorInfo;
 }
示例#19
0
 internal QueryChangeEventArgs(LiveQuery liveQuery, QueryEnumerator enumerator, Exception error)
 {
     Source = liveQuery;
     Rows   = enumerator;
     Error  = error;
 }