예제 #1
0
        /// <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));
            }
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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);
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
                }
            }
        }
예제 #8
0
        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);
                }
            }
        }
예제 #9
0
        /// <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"]);
            }
        }
예제 #10
0
        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;
                }
            }
        }
예제 #11
0
        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);
        }
예제 #12
0
		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;
		}
예제 #13
0
 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;
 }
예제 #14
0
        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));
        }
예제 #15
0
        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));
        }
예제 #16
0
		/// <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");
        }
예제 #18
0
        /// <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"]);
            }
        }
예제 #19
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="row">The wrapped row.</param>
        internal EntityQueryRow(QueryRow row)
        {
            Covenant.Requires <ArgumentNullException>(row != null);

            Base = row;
        }
예제 #20
0
        /// <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;
        }
예제 #21
0
        /// <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);
        }
예제 #22
0
 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;
 }
예제 #23
0
		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);
				}
			}
		}
예제 #24
0
        /// <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;
 }
예제 #26
0
        /// <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;
 }
예제 #28
0
        /// <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;
        }
예제 #29
0
 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);
         }
     }
 }