/// <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 database.GetAllDocs(new QueryOptions()); Query queryAllDocs = database.CreateAllDocumentsQuery(); QueryEnumerator queryEnumerator = queryAllDocs.Run(); for (IEnumerator <QueryRow> it = queryEnumerator; it.MoveNext();) { QueryRow row = it.Current; Assert.IsFalse(row.Document.Id.Equals(docId)); } }
public override bool Equals(object @object) { if (@object == this) { return(true); } if (!(@object is Couchbase.Lite.QueryRow)) { return(false); } Couchbase.Lite.QueryRow other = (Couchbase.Lite.QueryRow)@object; bool documentPropertiesEqual = Utils.IsEqual(documentProperties, other.GetDocumentProperties ()); if (database == other.database && Utils.IsEqual(key, other.GetKey()) && Utils.IsEqual (sourceDocumentId, other.GetSourceDocumentId()) && documentPropertiesEqual) { // If values were emitted, compare them. Otherwise we have nothing to go on so check // if _anything_ about the doc has changed (i.e. the sequences are different.) if (value != null || other.GetValue() != null) { return(value.Equals(other.GetValue())); } else { return(sequence == other.sequence); } } return(false); }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> internal IList <QueryRow> ReducedQuery(Cursor cursor, Boolean group, Int32 groupLevel) { IList <object> keysToReduce = null; IList <object> valuesToReduce = null; object lastKey = null; var reduce = Reduce; // FIXME: If reduce is null, then so are keysToReduce and ValuesToReduce, which can throw an NRE below. if (reduce != null) { keysToReduce = new AList <Object>(ReduceBatchSize); valuesToReduce = new AList <Object>(ReduceBatchSize); } var rows = new AList <QueryRow>(); cursor.MoveToNext(); while (!cursor.IsAfterLast()) { var keyData = FromJSON(cursor.GetBlob(0)); var value = FromJSON(cursor.GetBlob(1)); System.Diagnostics.Debug.Assert((keyData != null)); if (group && !GroupTogether(keyData, lastKey, groupLevel)) { if (lastKey != null) { // This pair starts a new group, so reduce & record the last one: var reduced = (reduce != null) ? reduce(keysToReduce, valuesToReduce, false) : null; var key = GroupKey(lastKey, groupLevel); var row = new QueryRow(null, 0, key, reduced, null); row.Database = Database; rows.AddItem(row); // NOTE.ZJG: Change to `yield return row` to convert to a generator. keysToReduce.Clear(); valuesToReduce.Clear(); } lastKey = keyData; } keysToReduce.AddItem(keyData); valuesToReduce.AddItem(value); cursor.MoveToNext(); } // NOTE.ZJG: Need to handle grouping differently if switching this to a generator. if (keysToReduce.Count > 0) { // Finish the last group (or the entire list, if no grouping): var key = group ? GroupKey(lastKey, groupLevel) : null; var reduced = (reduce != null) ? reduce(keysToReduce, valuesToReduce, false) : null; var row = new QueryRow(null, 0, key, reduced, null); row.Database = Database; rows.AddItem(row); } return(rows); }
/// <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); } }
internal IList <QueryRow> ReducedQuery(Cursor cursor, bool group, int groupLevel) { IList <object> keysToReduce = null; IList <object> valuesToReduce = null; object lastKey = null; if (GetReduce() != null) { keysToReduce = new AList <object>(ReduceBatchSize); valuesToReduce = new AList <object>(ReduceBatchSize); } IList <QueryRow> rows = new AList <QueryRow>(); cursor.MoveToNext(); while (!cursor.IsAfterLast()) { JsonDocument keyDoc = new JsonDocument(cursor.GetBlob(0)); JsonDocument valueDoc = new JsonDocument(cursor.GetBlob(1)); System.Diagnostics.Debug.Assert((keyDoc != null)); object keyObject = keyDoc.JsonObject(); if (group && !GroupTogether(keyObject, lastKey, groupLevel)) { if (lastKey != null) { // This pair starts a new group, so reduce & record the last one: object reduced = (reduceBlock != null) ? reduceBlock.Reduce(keysToReduce, valuesToReduce , false) : null; object key = GroupKey(lastKey, groupLevel); QueryRow row = new QueryRow(null, 0, key, reduced, null); row.SetDatabase(database); rows.AddItem(row); keysToReduce.Clear(); valuesToReduce.Clear(); } lastKey = keyObject; } keysToReduce.AddItem(keyObject); valuesToReduce.AddItem(valueDoc.JsonObject()); cursor.MoveToNext(); } if (keysToReduce.Count > 0) { // Finish the last group (or the entire list, if no grouping): object key = group ? GroupKey(lastKey, groupLevel) : null; object reduced = (reduceBlock != null) ? reduceBlock.Reduce(keysToReduce, valuesToReduce , false) : null; QueryRow row = new QueryRow(null, 0, key, reduced, null); row.SetDatabase(database); rows.AddItem(row); } return(rows); }
internal void LoadCurrentRevisionFrom(QueryRow row) { if (row.GetDocumentRevisionId() == null) { return; } string revId = row.GetDocumentRevisionId(); if (currentRevision == null || RevIdGreaterThanCurrent(revId)) { IDictionary <string, object> properties = row.GetDocumentProperties(); if (properties != null) { RevisionInternal rev = new RevisionInternal(properties, row.GetDatabase()); currentRevision = new SavedRevision(this, rev); } } }
internal void LoadCurrentRevisionFrom(QueryRow row) { if (row.DocumentRevisionId == null) { return; } var revId = row.DocumentRevisionId; if (currentRevision == null || RevIdGreaterThanCurrent(revId)) { var properties = row.DocumentProperties; if (properties != null) { var rev = new RevisionInternal(properties, row.Database); currentRevision = new SavedRevision(this, rev); } } }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestViewLinkedDocs() { PutLinkedDocs(database); View view = database.GetView("linked"); view.SetMapReduce(new _Mapper_1079(), null, "1"); view.UpdateIndex(); QueryOptions options = new QueryOptions(); options.SetIncludeDocs(true); // required for linked documents IList <QueryRow> rows = view.QueryWithOptions(options); NUnit.Framework.Assert.IsNotNull(rows); NUnit.Framework.Assert.AreEqual(5, rows.Count); object[][] expected = new object[][] { new object[] { "22222", "hello", 0, null, "22222" }, new object[] { "22222", "hello", 1, "11111", "11111" }, new object[] { "33333", "world", 0, null, "33333" }, new object[] { "33333", "world", 1, "22222" , "22222" }, new object[] { "33333", "world", 2, "11111", "11111" } }; for (int i = 0; i < rows.Count; i++) { QueryRow row = rows[i]; IDictionary <string, object> rowAsJson = row.AsJSONDictionary(); Log.D(Tag, string.Empty + rowAsJson); IList <object> key = (IList <object>)rowAsJson["key"]; IDictionary <string, object> doc = (IDictionary <string, object>)rowAsJson.Get("doc" ); string id = (string)rowAsJson["id"]; NUnit.Framework.Assert.AreEqual(expected[i][0], id); NUnit.Framework.Assert.AreEqual(2, key.Count); NUnit.Framework.Assert.AreEqual(expected[i][1], key[0]); NUnit.Framework.Assert.AreEqual(expected[i][2], key[1]); if (expected[i][3] == null) { NUnit.Framework.Assert.IsNull(row.GetValue()); } else { NUnit.Framework.Assert.AreEqual(expected[i][3], ((IDictionary <string, object>)row .GetValue())["_id"]); } NUnit.Framework.Assert.AreEqual(expected[i][4], doc["_id"]); } }
internal void LoadCurrentRevisionFrom(QueryRow row) { if (row.DocRevID == null) { return; } var revId = row.DocRevID; if (currentRevision == null || revId.CompareTo(CurrentRevisionId.AsRevID()) > 0) { ForgetCurrentRevision(); var rev = row.DocumentRevision; if (rev != null) { currentRevision = new SavedRevision(this, rev); _currentRevisionKnown = true; } } }
public IList <QueryRow> QueryWithOptions(QueryOptions options) { if (options == null) { options = new QueryOptions(); } Cursor cursor = null; IList <QueryRow> rows = new AList <QueryRow>(); try { cursor = ResultSetWithOptions(options); int groupLevel = options.GetGroupLevel(); bool group = options.IsGroup() || (groupLevel > 0); bool reduce = options.IsReduce() || group; if (reduce && (reduceBlock == null) && !group) { Log.W(Log.TagView, "Cannot use reduce option in view %s which has no reduce block defined" , name); throw new CouchbaseLiteException(new Status(Status.BadRequest)); } if (reduce || group) { // Reduced or grouped query: rows = ReducedQuery(cursor, group, groupLevel); } else { // regular query cursor.MoveToNext(); while (!cursor.IsAfterLast()) { JsonDocument keyDoc = new JsonDocument(cursor.GetBlob(0)); JsonDocument valueDoc = new JsonDocument(cursor.GetBlob(1)); string docId = cursor.GetString(2); int sequence = Sharpen.Extensions.ValueOf(cursor.GetString(3)); IDictionary <string, object> docContents = null; if (options.IsIncludeDocs()) { object valueObject = valueDoc.JsonObject(); // http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents if (valueObject is IDictionary && ((IDictionary)valueObject).ContainsKey("_id")) { string linkedDocId = (string)((IDictionary)valueObject).Get("_id"); RevisionInternal linkedDoc = database.GetDocumentWithIDAndRev(linkedDocId, null, EnumSet.NoneOf <Database.TDContentOptions>()); docContents = linkedDoc.GetProperties(); } else { docContents = database.DocumentPropertiesFromJSON(cursor.GetBlob(5), docId, cursor .GetString(4), false, cursor.GetLong(3), options.GetContentOptions()); } } QueryRow row = new QueryRow(docId, sequence, keyDoc.JsonObject(), valueDoc.JsonObject (), docContents); row.SetDatabase(database); rows.AddItem(row); cursor.MoveToNext(); } } } catch (SQLException e) { string errMsg = string.Format("Error querying view: %s", this); Log.E(Log.TagView, errMsg, e); throw new CouchbaseLiteException(errMsg, e, new Status(Status.DbError)); } finally { if (cursor != null) { cursor.Close(); } } return(rows); }
public IDictionary<string, object> GetAllDocs(QueryOptions options) { IDictionary<string, object> result = new Dictionary<string, object>(); IList<QueryRow> rows = new AList<QueryRow>(); if (options == null) { options = new QueryOptions(); } bool includeDeletedDocs = (options.GetAllDocsMode() == Query.AllDocsMode.IncludeDeleted ); long updateSeq = 0; if (options.IsUpdateSeq()) { updateSeq = GetLastSequenceNumber(); } // TODO: needs to be atomic with the following SELECT StringBuilder sql = new StringBuilder("SELECT revs.doc_id, docid, revid, sequence" ); if (options.IsIncludeDocs()) { sql.Append(", json"); } if (includeDeletedDocs) { sql.Append(", deleted"); } sql.Append(" FROM revs, docs WHERE"); if (options.GetKeys() != null) { if (options.GetKeys().Count == 0) { return result; } string commaSeperatedIds = JoinQuotedObjects(options.GetKeys()); sql.Append(string.Format(" revs.doc_id IN (SELECT doc_id FROM docs WHERE docid IN (%s)) AND" , commaSeperatedIds)); } sql.Append(" docs.doc_id = revs.doc_id AND current=1"); if (!includeDeletedDocs) { sql.Append(" AND deleted=0"); } IList<string> args = new AList<string>(); object minKey = options.GetStartKey(); object maxKey = options.GetEndKey(); bool inclusiveMin = true; bool inclusiveMax = options.IsInclusiveEnd(); if (options.IsDescending()) { minKey = maxKey; maxKey = options.GetStartKey(); inclusiveMin = inclusiveMax; inclusiveMax = true; } if (minKey != null) { System.Diagnostics.Debug.Assert((minKey is string)); sql.Append((inclusiveMin ? " AND docid >= ?" : " AND docid > ?")); args.AddItem((string)minKey); } if (maxKey != null) { System.Diagnostics.Debug.Assert((maxKey is string)); sql.Append((inclusiveMax ? " AND docid <= ?" : " AND docid < ?")); args.AddItem((string)maxKey); } sql.Append(string.Format(" ORDER BY docid %s, %s revid DESC LIMIT ? OFFSET ?", (options .IsDescending() ? "DESC" : "ASC"), (includeDeletedDocs ? "deleted ASC," : string.Empty ))); args.AddItem(Sharpen.Extensions.ToString(options.GetLimit())); args.AddItem(Sharpen.Extensions.ToString(options.GetSkip())); Cursor cursor = null; IDictionary<string, QueryRow> docs = new Dictionary<string, QueryRow>(); try { cursor = database.RawQuery(sql.ToString(), Sharpen.Collections.ToArray(args, new string[args.Count])); bool keepGoing = cursor.MoveToNext(); while (keepGoing) { long docNumericID = cursor.GetLong(0); string docId = cursor.GetString(1); string revId = cursor.GetString(2); long sequenceNumber = cursor.GetLong(3); bool deleted = includeDeletedDocs && cursor.GetInt(GetDeletedColumnIndex(options) ) > 0; IDictionary<string, object> docContents = null; if (options.IsIncludeDocs()) { byte[] json = cursor.GetBlob(4); docContents = DocumentPropertiesFromJSON(json, docId, revId, deleted, sequenceNumber , options.GetContentOptions()); } // Iterate over following rows with the same doc_id -- these are conflicts. // Skip them, but collect their revIDs if the 'conflicts' option is set: IList<string> conflicts = new AList<string>(); while (((keepGoing = cursor.MoveToNext()) == true) && cursor.GetLong(0) == docNumericID ) { if (options.GetAllDocsMode() == Query.AllDocsMode.ShowConflicts || options.GetAllDocsMode () == Query.AllDocsMode.OnlyConflicts) { if (conflicts.IsEmpty()) { conflicts.AddItem(revId); } conflicts.AddItem(cursor.GetString(2)); } } if (options.GetAllDocsMode() == Query.AllDocsMode.OnlyConflicts && conflicts.IsEmpty ()) { continue; } IDictionary<string, object> value = new Dictionary<string, object>(); value.Put("rev", revId); value.Put("_conflicts", conflicts); if (includeDeletedDocs) { value.Put("deleted", (deleted ? true : null)); } QueryRow change = new QueryRow(docId, sequenceNumber, docId, value, docContents); change.SetDatabase(this); if (options.GetKeys() != null) { docs.Put(docId, change); } else { rows.AddItem(change); } } if (options.GetKeys() != null) { foreach (object docIdObject in options.GetKeys()) { if (docIdObject is string) { string docId = (string)docIdObject; QueryRow change = docs.Get(docId); if (change == null) { IDictionary<string, object> value = new Dictionary<string, object>(); long docNumericID = GetDocNumericID(docId); if (docNumericID > 0) { bool deleted; IList<bool> outIsDeleted = new AList<bool>(); IList<bool> outIsConflict = new AList<bool>(); string revId = WinningRevIDOfDoc(docNumericID, outIsDeleted, outIsConflict); if (outIsDeleted.Count > 0) { deleted = true; } if (revId != null) { value.Put("rev", revId); value.Put("deleted", true); } } change = new QueryRow((value != null ? docId : null), 0, docId, value, null); change.SetDatabase(this); } rows.AddItem(change); } } } } catch (SQLException e) { Log.E(Database.Tag, "Error getting all docs", e); throw new CouchbaseLiteException("Error getting all docs", e, new Status(Status.InternalServerError )); } finally { if (cursor != null) { cursor.Close(); } } result.Put("rows", rows); result.Put("total_rows", rows.Count); result.Put("offset", options.GetSkip()); if (updateSeq != 0) { result.Put("update_seq", updateSeq); } return result; }
internal IList<QueryRow> ReducedQuery(Cursor cursor, bool group, int groupLevel) { IList<object> keysToReduce = null; IList<object> valuesToReduce = null; object lastKey = null; if (GetReduce() != null) { keysToReduce = new AList<object>(ReduceBatchSize); valuesToReduce = new AList<object>(ReduceBatchSize); } IList<QueryRow> rows = new AList<QueryRow>(); cursor.MoveToNext(); while (!cursor.IsAfterLast()) { JsonDocument keyDoc = new JsonDocument(cursor.GetBlob(0)); JsonDocument valueDoc = new JsonDocument(cursor.GetBlob(1)); System.Diagnostics.Debug.Assert((keyDoc != null)); object keyObject = keyDoc.JsonObject(); if (group && !GroupTogether(keyObject, lastKey, groupLevel)) { if (lastKey != null) { // This pair starts a new group, so reduce & record the last one: object reduced = (reduceBlock != null) ? reduceBlock.Reduce(keysToReduce, valuesToReduce , false) : null; object key = GroupKey(lastKey, groupLevel); QueryRow row = new QueryRow(null, 0, key, reduced, null); row.SetDatabase(database); rows.AddItem(row); keysToReduce.Clear(); valuesToReduce.Clear(); } lastKey = keyObject; } keysToReduce.AddItem(keyObject); valuesToReduce.AddItem(valueDoc.JsonObject()); cursor.MoveToNext(); } if (keysToReduce.Count > 0) { // Finish the last group (or the entire list, if no grouping): object key = group ? GroupKey(lastKey, groupLevel) : null; object reduced = (reduceBlock != null) ? reduceBlock.Reduce(keysToReduce, valuesToReduce , false) : null; QueryRow row = new QueryRow(null, 0, key, reduced, null); row.SetDatabase(database); rows.AddItem(row); } return rows; }
public void TestAllDocsQuery() { var docs = PutDocs(database); var expectedRow = new AList<QueryRow>(); foreach (RevisionInternal rev in docs) { var value = new Dictionary<string, object>(); value.Put("rev", rev.GetRevId()); value.Put("_conflicts", new AList<string>()); var queryRow = new QueryRow(rev.GetDocId(), 0, rev.GetDocId(), value, null); queryRow.Database = database; expectedRow.AddItem(queryRow); } var options = new QueryOptions(); var allDocs = database.GetAllDocs(options); var expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); var expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); //CollectionAssert.AreEqual(expectedQueryResult, allDocs); AssertPropertiesAreEqual(expectedQueryResult, allDocs); // Start/end key query: options = new QueryOptions(); options.SetStartKey("2"); options.SetEndKey("44444"); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Start/end query without inclusive end: options.SetInclusiveEnd(false); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Get all documents: with default QueryOptions options = new QueryOptions(); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Get specific documents: options = new QueryOptions(); IList<object> docIds = new AList<object>(); QueryRow expected2 = expectedRow[2]; docIds.AddItem(expected2.Document.Id); options.SetKeys(docIds); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expected2); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); }
public void TestAllDocsQuery() { var docs = PutDocs(database); var expectedRow = new List <QueryRow>(); foreach (RevisionInternal rev in docs) { var value = new Dictionary <string, object>(); value.Put("rev", rev.GetRevId()); value.Put("_conflicts", new List <string>()); var queryRow = new QueryRow(rev.GetDocId(), 0, rev.GetDocId(), value, null); queryRow.Database = database; expectedRow.AddItem(queryRow); } var options = new QueryOptions(); var allDocs = database.GetAllDocs(options); var expectedRows = new List <QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); var expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); //CollectionAssert.AreEqual(expectedQueryResult, allDocs); AssertPropertiesAreEqual(expectedQueryResult, allDocs); // Start/end key query: options = new QueryOptions(); options.SetStartKey("2"); options.SetEndKey("44444"); allDocs = database.GetAllDocs(options); expectedRows = new List <QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Start/end query without inclusive end: options.SetInclusiveEnd(false); allDocs = database.GetAllDocs(options); expectedRows = new List <QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Get all documents: with default QueryOptions options = new QueryOptions(); allDocs = database.GetAllDocs(options); expectedRows = new List <QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); // Get specific documents: options = new QueryOptions(); IList <object> docIds = new List <object>(); QueryRow expected2 = expectedRow[2]; docIds.AddItem(expected2.Document.Id); options.SetKeys(docIds); allDocs = database.GetAllDocs(options); expectedRows = new List <QueryRow>(); expectedRows.AddItem(expected2); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); Assert.AreEqual(expectedQueryResult.Select(kvp => kvp.Key).OrderBy(k => k), allDocs.Select(kvp => kvp.Key).OrderBy(k => k)); }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestAllDocsQuery() { IList<RevisionInternal> docs = PutDocs(database); IList<QueryRow> expectedRow = new AList<QueryRow>(); foreach (RevisionInternal rev in docs) { IDictionary<string, object> value = new Dictionary<string, object>(); value.Put("rev", rev.GetRevId()); value.Put("_conflicts", new AList<string>()); QueryRow queryRow = new QueryRow(rev.GetDocId(), 0, rev.GetDocId(), value, null); queryRow.SetDatabase(database); expectedRow.AddItem(queryRow); } QueryOptions options = new QueryOptions(); IDictionary<string, object> allDocs = database.GetAllDocs(options); IList<QueryRow> expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); IDictionary<string, object> expectedQueryResult = CreateExpectedQueryResult(expectedRows , 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Start/end key query: options = new QueryOptions(); options.SetStartKey("2"); options.SetEndKey("44444"); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Start/end query without inclusive end: options.SetInclusiveEnd(false); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Get all documents: with default QueryOptions options = new QueryOptions(); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Get specific documents: options = new QueryOptions(); IList<object> docIds = new AList<object>(); QueryRow expected2 = expectedRow[2]; docIds.AddItem(expected2.GetDocument().GetId()); options.SetKeys(docIds); allDocs = database.GetAllDocs(options); expectedRows = new AList<QueryRow>(); expectedRows.AddItem(expected2); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); }
public override void WillUseCell (CouchbaseTableSource source, UITableViewCell cell, QueryRow row) { if (backgroundColor == null) { var image = UIImage.FromBundle ("item_background"); backgroundColor = UIColor.FromPatternImage (image); } cell.BackgroundColor = backgroundColor; cell.SelectionStyle = UITableViewCellSelectionStyle.Gray; cell.TextLabel.Font = UIFont.FromName ("Helvetica", 18f); cell.TextLabel.BackgroundColor = UIColor.Clear; var props = (IDictionary<string, object>)row.Value; var isChecked = (bool)props[RootViewController.CheckboxPropertyName]; // props.TryGetValue (RootViewController.CheckboxPropertyName, out isChecked); cell.TextLabel.TextColor = (bool)isChecked ? UIColor.Gray : UIColor.Black; cell.ImageView.Image = UIImage.FromBundle ((bool)isChecked ? "list_area___checkbox___checked" : "list_area___checkbox___unchecked"); }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestViewLinkedDocs() { PutLinkedDocs(database); View view = database.GetView("linked"); view.SetMapReduce((document, emitter) => { if (document.ContainsKey("value")) { emitter(new object[] { document["value"], 0 }, null); } if (document.ContainsKey("ancestors")) { IList <object> ancestors = (IList <object>)document["ancestors"]; for (int i = 0; i < ancestors.Count; i++) { IDictionary <string, object> value = new Dictionary <string, object>(); value["_id"] = ancestors[i]; emitter(new object[] { document["value"], i + 1 }, value); } } }, null, "1.0"); view.UpdateIndex(); QueryOptions options = new QueryOptions(); options.SetIncludeDocs(true); // required for linked documents IList <QueryRow> rows = view.QueryWithOptions(options).ToList(); Assert.IsNotNull(rows); Assert.AreEqual(5, rows.Count); object[][] expected = new object[][] { new object[] { "22222", "hello", 0, null, "22222" }, new object[] { "22222", "hello", 1, "11111", "11111" }, new object[] { "33333", "world", 0, null, "33333" }, new object[] { "33333", "world", 1, "22222", "22222" }, new object[] { "33333", "world", 2, "11111", "11111" } }; for (int i = 0; i < rows.Count; i++) { QueryRow row = rows[i]; IDictionary <string, object> rowAsJson = row.AsJSONDictionary(); Log.D(Tag, string.Empty + rowAsJson); IList <object> key = (IList <object>)rowAsJson["key"]; IDictionary <string, object> doc = (IDictionary <string, object>)rowAsJson.Get("doc" ); string id = (string)rowAsJson["id"]; Assert.AreEqual(expected[i][0], id); Assert.AreEqual(2, key.Count); Assert.AreEqual(expected[i][1], key[0]); Assert.AreEqual(expected[i][2], key[1]); if (expected[i][3] == null) { Assert.IsNull(row.Value); } else { Assert.AreEqual(expected[i][3], ((IDictionary <string, object>)row.Value)["_id"]); } Assert.AreEqual(expected[i][4], doc["_id"]); } }
/// <summary> /// Constructor. /// </summary> /// <param name="row">The wrapped row.</param> internal EntityQueryRow(QueryRow row) { Covenant.Requires <ArgumentNullException>(row != null); Base = row; }
/// <summary>Queries the view.</summary> /// <remarks>Queries the view. Does NOT first update the index.</remarks> /// <param name="options">The options to use.</param> /// <returns>An array of QueryRow objects.</returns> /// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> internal IEnumerable<QueryRow> QueryWithOptions(QueryOptions options) { if (options == null) options = new QueryOptions(); Cursor cursor = null; IList<QueryRow> rows = new AList<QueryRow>(); try { cursor = ResultSetWithOptions(options); int groupLevel = options.GetGroupLevel(); var group = options.IsGroup() || (groupLevel > 0); var reduce = options.IsReduce() || group; var reduceBlock = Reduce; if (reduce && (reduceBlock == null) && !group) { var msg = "Cannot use reduce option in view " + Name + " which has no reduce block defined"; Log.W(Database.Tag, msg); throw new CouchbaseLiteException(StatusCode.BadRequest); } if (reduce || group) { // Reduced or grouped query: rows = ReducedQuery(cursor, group, groupLevel); } else { // regular query cursor.MoveToNext(); while (!cursor.IsAfterLast()) { var keyData = FromJSON(cursor.GetBlob(0)); // TODO: delay parsing this for increased efficiency var value = FromJSON(cursor.GetBlob(1)); // TODO: ditto var docId = cursor.GetString(2); var sequenceLong = cursor.GetLong(3); var sequence = Convert.ToInt32(sequenceLong); IDictionary<string, object> docContents = null; if (options.IsIncludeDocs()) { // http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents if (value is IDictionary<string,object> && ((IDictionary<string,object>)value).ContainsKey("_id")) { string linkedDocId = (string)((IDictionary<string,object>)value).Get("_id"); RevisionInternal linkedDoc = Database.GetDocumentWithIDAndRev(linkedDocId, null, EnumSet.NoneOf<TDContentOptions>()); docContents = linkedDoc.GetProperties(); } else { var revId = cursor.GetString(4); docContents = Database.DocumentPropertiesFromJSON(cursor.GetBlob(5), docId, revId, false, sequenceLong, options.GetContentOptions()); } } var row = new QueryRow(docId, sequence, keyData, value, docContents); row.Database = Database; rows.AddItem<QueryRow>(row); // NOTE.ZJG: Change to `yield return row` to convert to a generator. cursor.MoveToNext(); } } } catch (SQLException e) { var errMsg = string.Format("Error querying view: {0}", this); Log.E(Database.Tag, errMsg, e); throw new CouchbaseLiteException(errMsg, e, new Status(StatusCode.DbError)); } finally { if (cursor != null) { cursor.Close(); } } return rows; }
/// <summary>Queries the view.</summary> /// <remarks>Queries the view. Does NOT first update the index.</remarks> /// <param name="options">The options to use.</param> /// <returns>An array of QueryRow objects.</returns> /// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> internal IEnumerable <QueryRow> QueryWithOptions(QueryOptions options) { if (options == null) { options = new QueryOptions(); } Cursor cursor = null; IList <QueryRow> rows = new List <QueryRow>(); try { cursor = ResultSetWithOptions(options); int groupLevel = options.GetGroupLevel(); var group = options.IsGroup() || (groupLevel > 0); var reduceBlock = Reduce; var reduce = GroupOrReduce(options); if (reduce && (reduceBlock == null) && !group) { var msg = "Cannot use reduce option in view " + Name + " which has no reduce block defined"; Log.W(Database.Tag, msg); throw new CouchbaseLiteException(StatusCode.BadRequest); } if (reduce || group) { // Reduced or grouped query: rows = ReducedQuery(cursor, group, groupLevel); } else { // regular query cursor.MoveToNext(); while (!cursor.IsAfterLast()) { var key = FromJSON(cursor.GetBlob(0)); var value = FromJSON(cursor.GetBlob(1)); var docId = cursor.GetString(2); var sequenceLong = cursor.GetLong(3); var sequence = Convert.ToInt32(sequenceLong); IDictionary <string, object> docContents = null; if (options.IsIncludeDocs()) { // http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents if (value is IDictionary <string, object> && ((IDictionary <string, object>)value).ContainsKey("_id")) { var linkedDocId = (string)((IDictionary <string, object>)value).Get("_id"); var linkedDoc = Database.GetDocumentWithIDAndRev(linkedDocId, null, DocumentContentOptions.None); docContents = linkedDoc.GetProperties(); } else { var revId = cursor.GetString(4); docContents = Database.DocumentPropertiesFromJSON(cursor.GetBlob(5), docId, revId, false, sequenceLong, options.GetContentOptions()); } } var row = new QueryRow(docId, sequence, key, value, docContents); row.Database = Database; rows.AddItem <QueryRow>(row); // NOTE.ZJG: Change to `yield return row` to convert to a generator. cursor.MoveToNext(); } } } catch (SQLException e) { var errMsg = string.Format("Error querying view: {0}", this); Log.E(Database.Tag, errMsg, e); throw new CouchbaseLiteException(errMsg, e, new Status(StatusCode.DbError)); } finally { if (cursor != null) { cursor.Close(); } } return(rows); }
public IList<QueryRow> QueryWithOptions(QueryOptions options) { if (options == null) { options = new QueryOptions(); } Cursor cursor = null; IList<QueryRow> rows = new AList<QueryRow>(); try { cursor = ResultSetWithOptions(options); int groupLevel = options.GetGroupLevel(); bool group = options.IsGroup() || (groupLevel > 0); bool reduce = options.IsReduce() || group; if (reduce && (reduceBlock == null) && !group) { Log.W(Log.TagView, "Cannot use reduce option in view %s which has no reduce block defined" , name); throw new CouchbaseLiteException(new Status(Status.BadRequest)); } if (reduce || group) { // Reduced or grouped query: rows = ReducedQuery(cursor, group, groupLevel); } else { // regular query cursor.MoveToNext(); while (!cursor.IsAfterLast()) { JsonDocument keyDoc = new JsonDocument(cursor.GetBlob(0)); JsonDocument valueDoc = new JsonDocument(cursor.GetBlob(1)); string docId = cursor.GetString(2); int sequence = Sharpen.Extensions.ValueOf(cursor.GetString(3)); IDictionary<string, object> docContents = null; if (options.IsIncludeDocs()) { object valueObject = valueDoc.JsonObject(); // http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents if (valueObject is IDictionary && ((IDictionary)valueObject).ContainsKey("_id")) { string linkedDocId = (string)((IDictionary)valueObject).Get("_id"); RevisionInternal linkedDoc = database.GetDocumentWithIDAndRev(linkedDocId, null, EnumSet.NoneOf<Database.TDContentOptions>()); docContents = linkedDoc.GetProperties(); } else { docContents = database.DocumentPropertiesFromJSON(cursor.GetBlob(5), docId, cursor .GetString(4), false, cursor.GetLong(3), options.GetContentOptions()); } } QueryRow row = new QueryRow(docId, sequence, keyDoc.JsonObject(), valueDoc.JsonObject (), docContents); row.SetDatabase(database); rows.AddItem(row); cursor.MoveToNext(); } } } catch (SQLException e) { string errMsg = string.Format("Error querying view: %s", this); Log.E(Log.TagView, errMsg, e); throw new CouchbaseLiteException(errMsg, e, new Status(Status.DbError)); } finally { if (cursor != null) { cursor.Close(); } } return rows; }
internal void LoadCurrentRevisionFrom(QueryRow row) { if (row.GetDocumentRevisionId() == null) { return; } string revId = row.GetDocumentRevisionId(); if (currentRevision == null || RevIdGreaterThanCurrent(revId)) { IDictionary<string, object> properties = row.GetDocumentProperties(); if (properties != null) { RevisionInternal rev = new RevisionInternal(properties, row.GetDatabase()); currentRevision = new SavedRevision(this, rev); } } }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestAllDocsQuery() { IList <RevisionInternal> docs = PutDocs(database); IList <QueryRow> expectedRow = new AList <QueryRow>(); foreach (RevisionInternal rev in docs) { IDictionary <string, object> value = new Dictionary <string, object>(); value.Put("rev", rev.GetRevId()); value.Put("_conflicts", new AList <string>()); QueryRow queryRow = new QueryRow(rev.GetDocId(), 0, rev.GetDocId(), value, null); queryRow.SetDatabase(database); expectedRow.AddItem(queryRow); } QueryOptions options = new QueryOptions(); IDictionary <string, object> allDocs = database.GetAllDocs(options); IList <QueryRow> expectedRows = new AList <QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); IDictionary <string, object> expectedQueryResult = CreateExpectedQueryResult(expectedRows , 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Start/end key query: options = new QueryOptions(); options.StartKey = "2"; options.EndKey = "44444"; allDocs = database.GetAllDocs(options); expectedRows = new AList <QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Start/end query without inclusive end: options.SetInclusiveEnd(false); allDocs = database.GetAllDocs(options); expectedRows = new AList <QueryRow>(); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Get all documents: with default QueryOptions options = new QueryOptions(); allDocs = database.GetAllDocs(options); expectedRows = new AList <QueryRow>(); expectedRows.AddItem(expectedRow[2]); expectedRows.AddItem(expectedRow[0]); expectedRows.AddItem(expectedRow[3]); expectedRows.AddItem(expectedRow[1]); expectedRows.AddItem(expectedRow[4]); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); // Get specific documents: options = new QueryOptions(); IList <object> docIds = new AList <object>(); QueryRow expected2 = expectedRow[2]; docIds.AddItem(expected2.Document.Id); options.SetKeys(docIds); allDocs = database.GetAllDocs(options); expectedRows = new AList <QueryRow>(); expectedRows.AddItem(expected2); expectedQueryResult = CreateExpectedQueryResult(expectedRows, 0); NUnit.Framework.Assert.AreEqual(expectedQueryResult, allDocs); }
public override void UpdateFromQuery(CouchbaseTableSource source, LiveQuery query, QueryRow[] previousRows) { return; }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> internal IDictionary<String, Object> GetAllDocs(QueryOptions options) { var result = new Dictionary<String, Object>(); var rows = new AList<QueryRow>(); if (options == null) options = new QueryOptions(); var includeDeletedDocs = (options.GetAllDocsMode() == AllDocsMode.IncludeDeleted); var updateSeq = 0L; if (options.IsUpdateSeq()) { updateSeq = GetLastSequenceNumber(); } // TODO: needs to be atomic with the following SELECT var sql = new StringBuilder("SELECT revs.doc_id, docid, revid, sequence"); if (options.IsIncludeDocs()) { sql.Append(", json"); } if (includeDeletedDocs) { sql.Append(", deleted"); } sql.Append(" FROM revs, docs WHERE"); if (options.GetKeys() != null) { if (options.GetKeys().Count() == 0) { return result; } var commaSeperatedIds = JoinQuotedObjects(options.GetKeys()); sql.Append(String.Format(" revs.doc_id IN (SELECT doc_id FROM docs WHERE docid IN ({0})) AND", commaSeperatedIds)); } sql.Append(" docs.doc_id = revs.doc_id AND current=1"); if (!includeDeletedDocs) { sql.Append(" AND deleted=0"); } var args = new AList<String>(); var minKey = options.GetStartKey(); var maxKey = options.GetEndKey(); var inclusiveMin = true; var inclusiveMax = options.IsInclusiveEnd(); if (options.IsDescending()) { minKey = maxKey; maxKey = options.GetStartKey(); inclusiveMin = inclusiveMax; inclusiveMax = true; } if (minKey != null) { Debug.Assert((minKey is String)); sql.Append((inclusiveMin ? " AND docid >= ?" : " AND docid > ?")); args.AddItem((string)minKey); } if (maxKey != null) { Debug.Assert((maxKey is string)); sql.Append((inclusiveMax ? " AND docid <= ?" : " AND docid < ?")); args.AddItem((string)maxKey); } sql.Append( String.Format(" ORDER BY docid {0}, {1} revid DESC LIMIT ? OFFSET ?", options.IsDescending() ? "DESC" : "ASC", includeDeletedDocs ? "deleted ASC," : String.Empty ) ); args.AddItem(options.GetLimit().ToString()); args.AddItem(options.GetSkip().ToString()); Cursor cursor = null; var docs = new Dictionary<String, QueryRow>(); try { cursor = StorageEngine.RawQuery( sql.ToString(), CommandBehavior.SequentialAccess, args.ToArray() ); // cursor.MoveToNext(); var keepGoing = cursor.MoveToNext(); while (keepGoing) { var docNumericID = cursor.GetLong(0); var includeDocs = options.IsIncludeDocs(); var docId = cursor.GetString(1); var revId = cursor.GetString(2); var sequenceNumber = cursor.GetLong(3); byte[] json = null; if (includeDocs) { json = cursor.GetBlob(4); } var deleted = includeDeletedDocs && cursor.GetInt(GetDeletedColumnIndex(options)) > 0; IDictionary<String, Object> docContents = null; if (includeDocs) { docContents = DocumentPropertiesFromJSON(json, docId, revId, deleted, sequenceNumber, options.GetContentOptions()); } // Iterate over following rows with the same doc_id -- these are conflicts. // Skip them, but collect their revIDs if the 'conflicts' option is set: var conflicts = new List<string>(); while (((keepGoing = cursor.MoveToNext())) && cursor.GetLong(0) == docNumericID) { if (options.GetAllDocsMode() == AllDocsMode.ShowConflicts || options.GetAllDocsMode() == AllDocsMode.OnlyConflicts) { if (conflicts.IsEmpty()) { conflicts.AddItem(revId); } conflicts.AddItem(cursor.GetString(2)); } } if (options.GetAllDocsMode() == AllDocsMode.OnlyConflicts && conflicts.IsEmpty()) { continue; } var value = new Dictionary<string, object>(); value["rev"] = revId; value["_conflicts"] = conflicts; if (includeDeletedDocs) { value["deleted"] = deleted; } var change = new QueryRow(docId, sequenceNumber, docId, value, docContents); change.Database = this; if (options.GetKeys() != null) { docs[docId] = change; } else { rows.AddItem(change); } } if (options.GetKeys() != null) { foreach (var docIdObject in options.GetKeys()) { if (docIdObject is string) { var docId = (string)docIdObject; var change = docs.Get(docId); if (change == null) { var value = new Dictionary<string, object>(); var docNumericID = GetDocNumericID(docId); if (docNumericID > 0) { bool deleted; var outIsDeleted = new AList<bool>(); var outIsConflict = new AList<bool>(); var revId = WinningRevIDOfDoc(docNumericID, outIsDeleted, outIsConflict); if (outIsDeleted.Count > 0) { deleted = true; } if (revId != null) { value["rev"] = revId; value["deleted"] = true; // FIXME: SHould this be set the value of `deleted`? } } change = new QueryRow((value != null ? docId : null), 0, docId, value, null); change.Database = this; } rows.AddItem(change); } } } } catch (SQLException e) { Log.E(Tag, "Error getting all docs", e); throw new CouchbaseLiteException("Error getting all docs", e, new Status(StatusCode.InternalServerError)); } finally { if (cursor != null) cursor.Close(); } result["rows"] = rows; result["total_rows"] = rows.Count; result.Put("offset", options.GetSkip()); if (updateSeq != 0) { result["update_seq"] = updateSeq; } return result; }
public override bool DeleteRow(CouchbaseTableSource source, QueryRow row) { return false; }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> internal IList<QueryRow> ReducedQuery(Cursor cursor, Boolean group, Int32 groupLevel) { IList<object> keysToReduce = null; IList<object> valuesToReduce = null; object lastKey = null; var reduce = Reduce; // FIXME: If reduce is null, then so are keysToReduce and ValuesToReduce, which can throw an NRE below. if (reduce != null) { keysToReduce = new AList<Object>(ReduceBatchSize); valuesToReduce = new AList<Object>(ReduceBatchSize); } var rows = new AList<QueryRow>(); cursor.MoveToNext(); while (!cursor.IsAfterLast()) { var keyData = FromJSON(cursor.GetBlob(0)); var value = FromJSON(cursor.GetBlob(1)); System.Diagnostics.Debug.Assert((keyData != null)); if (group && !GroupTogether(keyData, lastKey, groupLevel)) { if (lastKey != null) { // This pair starts a new group, so reduce & record the last one: var reduced = (reduce != null) ? reduce(keysToReduce, valuesToReduce, false) : null; var key = GroupKey(lastKey, groupLevel); var row = new QueryRow(null, 0, key, reduced, null); row.Database = Database; rows.AddItem(row); // NOTE.ZJG: Change to `yield return row` to convert to a generator. keysToReduce.Clear(); valuesToReduce.Clear(); } lastKey = keyData; } keysToReduce.AddItem(keyData); valuesToReduce.AddItem(value); cursor.MoveToNext(); } // NOTE.ZJG: Need to handle grouping differently if switching this to a generator. if (keysToReduce.Count > 0) { // Finish the last group (or the entire list, if no grouping): var key = group ? GroupKey(lastKey, groupLevel) : null; var reduced = (reduce != null) ? reduce(keysToReduce, valuesToReduce, false) : null; var row = new QueryRow(null, 0, key, reduced, null); row.Database = Database; rows.AddItem(row); } return rows; }