Example #1
0
        public void CanCorrectlyParseContainsExpression()
        {
            var options = new TestOptions
            {
                Filters = new Dictionary <string, string>
                {
                    { "Value", "%two%" }
                }
            };

            var list = QueryOptions.Filter(_items, options);

            Assert.Contains("Value.Contains(\"two\")", list.Expression.ToString());
        }
Example #2
0
        public void CanCorrectlyParseGuidParameter()
        {
            var options = new TestOptions
            {
                Filters = new Dictionary <string, string>
                {
                    { "Id", $"={_id:D}" }
                }
            };

            var list = QueryOptions.Filter(_items, options);

            Assert.Contains($"Id == {_id:D}", list.Expression.ToString());
        }
Example #3
0
        public void CanCorrectlyParseLessThanEqualsWithDateExpression()
        {
            var options = new TestOptions
            {
                Filters = new Dictionary <string, string>
                {
                    { "Date", "<=2020-01-01T12:30:00Z" }
                }
            };

            var list = QueryOptions.Filter(_items, options);

            Assert.Contains("r.Date <= 1/01/2020 11:30:00 PM", list.Expression.ToString());
        }
Example #4
0
        public void CanCorrectlyParseLessThanEqualsExpression()
        {
            var options = new TestOptions
            {
                Filters = new Dictionary <string, string>
                {
                    { "Numeric", "<=20" }
                }
            };

            var list = QueryOptions.Filter(_items, options);

            Assert.Contains("r.Numeric <= 20", list.Expression.ToString());
        }
Example #5
0
        public void CanCorrectlyParseContainsArrayWithNotExpression()
        {
            var options = new TestOptions
            {
                Filters = new Dictionary <string, string>
                {
                    { "Value", "!(one,two)" }
                }
            };

            var list = QueryOptions.Filter(_items, options);

            Assert.Contains("Not(new [] {\"one\", \"two\"}.Contains(r.Value))", list.Expression.ToString());
        }
        public IEnumerable <QueryRow> ReducedQuery(QueryOptions options)
        {
            var  db         = _dbStorage;
            var  groupLevel = options.GroupLevel;
            bool group      = options.Group || groupLevel > 0;
            var  reduce     = Delegate.Reduce;

            if (options.ReduceSpecified)
            {
                if (options.Reduce && reduce == null)
                {
                    Log.W(TAG, "Cannot use reduce option in view {0} which has no reduce block defined", Name);
                    return(null);
                }
            }

            List <object> keysToReduce = null, valuesToReduce = null;

            if (reduce != null)
            {
                keysToReduce   = new List <object>(100);
                valuesToReduce = new List <object>(100);
            }

            Lazy <byte[]>   lastKeyData = null;
            List <QueryRow> rows        = new List <QueryRow>();

            RunQuery(options, (keyData, valueData, docID, c) =>
            {
                var lastKeyValue = lastKeyData != null ? lastKeyData.Value : null;
                if (group && !GroupTogether(keyData.Value, lastKeyValue, groupLevel))
                {
                    if (lastKeyData != null && lastKeyData.Value != null)
                    {
                        // This pair starts a new group, so reduce & record the last one:
                        var key     = GroupKey(lastKeyData.Value, groupLevel);
                        var reduced = CallReduce(reduce, keysToReduce, valuesToReduce);
                        var row     = new QueryRow(null, 0, key, reduced, null, this);
                        if (options.Filter == null || options.Filter(row))
                        {
                            rows.Add(row);
                        }

                        keysToReduce.Clear();
                        valuesToReduce.Clear();
                    }
                    lastKeyData = keyData;
                }

                Log.V(TAG, "    Query {0}: Will reduce row with key={1}, value={2}", Name, keyData.Value, valueData.Value);

                object valueOrData = FromJSON(valueData.Value);
                if (valuesToReduce != null && RowValueIsEntireDoc(valueData.Value))
                {
                    // map fn emitted 'doc' as value, which was stored as a "*" placeholder; expand now:
                    try {
                        var rev     = db.GetDocument(docID, c.GetLong(1));
                        valueOrData = rev.GetProperties();
                    } catch (CouchbaseLiteException) {
                        Log.W(TAG, "Couldn't load doc for row value");
                        throw;
                    }
                }

                keysToReduce.Add(keyData.Value);
                valuesToReduce.Add(valueOrData);
                return(new Status(StatusCode.Ok));
            });

            if ((keysToReduce != null && keysToReduce.Count > 0) || lastKeyData != null)
            {
                // Finish the last group (or the entire list, if no grouping):
                var key     = group ? GroupKey(lastKeyData.Value, groupLevel) : null;
                var reduced = CallReduce(reduce, keysToReduce, valuesToReduce);
                Log.V(TAG, "    Query {0}: Will reduce row with key={1}, value={2}", Name, Manager.GetObjectMapper().WriteValueAsString(key),
                      Manager.GetObjectMapper().WriteValueAsString(reduced));

                var row = new QueryRow(null, 0, key, reduced, null, this);
                if (options.Filter == null || options.Filter(row))
                {
                    rows.Add(row);
                }
            }

            return(rows);
        }
Example #7
0
        public IEnumerable <QueryRow> GetAllDocs(QueryOptions options)
        {
            var remainingIDs = default(List <string>);
            var enumerator   = GetDocEnumerator(options, out remainingIDs);
            var current      = 0;

            foreach (var next in enumerator)
            {
                if (current++ >= options.Limit)
                {
                    yield break;
                }

                var sequenceNumber = 0L;
                var docID          = next.CurrentDocID;
                remainingIDs.Remove(docID);
                var value = default(IDictionary <string, object>);
                if (next.Exists)
                {
                    sequenceNumber = (long)next.SelectedRev.sequence;
                    var conflicts = default(IList <string>);
                    if (options.AllDocsMode >= AllDocsMode.ShowConflicts && next.IsConflicted)
                    {
                        SelectCurrentRevision(next);
                        LoadRevisionBody(next);
                        using (var innerEnumerator = new CBForestHistoryEnumerator(next, true, false)) {
                            conflicts = innerEnumerator.Select(x => (string)x.SelectedRev.revID).ToList();
                        }

                        if (conflicts.Count == 1)
                        {
                            conflicts = null;
                        }
                    }

                    bool valid = conflicts != null || options.AllDocsMode != AllDocsMode.OnlyConflicts;
                    if (!valid)
                    {
                        continue;
                    }

                    value = new NonNullDictionary <string, object> {
                        { "rev", next.CurrentRevID },
                        { "deleted", next.IsDeleted ? (object)true : null },
                        { "_conflicts", conflicts }
                    };
                }

                var row = new QueryRow(value == null ? null : docID, sequenceNumber, docID, value,
                                       value == null ? null : new RevisionInternal(next, options.IncludeDocs), null);
                if (options.Filter == null || options.Filter(row))
                {
                    yield return(row);
                }
            }

            foreach (var docId in remainingIDs)
            {
                var value = GetAllDocsEntry(docId);


                var row = new QueryRow(value != null ? docId as string : null, 0, docId, value, null, null);
                if (options.Filter == null || options.Filter(row))
                {
                    yield return(row);
                }
            }
        }