Esempio n. 1
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;
        }
Esempio n. 2
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;
        }
Esempio n. 3
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;
		}
        /// <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 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");
        }
Esempio n. 6
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 UpdateFromQuery(CouchbaseTableSource source, LiveQuery query, QueryRow[] previousRows)
 {
     return;
 }
 public override bool DeleteRow(CouchbaseTableSource source, QueryRow row)
 {
     return false;
 }
Esempio n. 9
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);
				}
			}
		}
Esempio n. 10
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;
 }
Esempio n. 11
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;
 }
Esempio n. 12
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));
        }
Esempio n. 13
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);
         }
     }
 }