private void SetRows(QueryEnumerator queryEnumerator) { lock (this) { rows = queryEnumerator; } }
/// <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; }
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; } }
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(); }
//--------------------------------------------------------------------- // IDisposable implementation /// <inheritdoc/> public void Dispose() { if (Base != null) { Base.Dispose(); Base = null; } }
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); }
/// <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)); }
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); } }
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; }
/// <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; }
internal QueryChangeEventArgs(LiveQuery liveQuery, QueryEnumerator enumerator, Exception error) { Source = liveQuery; Rows = enumerator; Error = error; }