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()); }
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()); }
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()); }
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()); }
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); }
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); } } }