public IEnumerable <QueryRow> RegularQuery(QueryOptions options) { var optionsCopy = options.Copy(); // Needed because Count() and ElementAt() will share this var filter = optionsCopy.Filter; var limit = Int32.MaxValue; var skip = 0; if (filter != null) { // If a filter is present, these need to be applied to the filter // and not the query limit = optionsCopy.Limit; skip = optionsCopy.Skip; optionsCopy.Limit = Int32.MaxValue; optionsCopy.Skip = 0; } var enumerator = QueryEnumeratorWithOptions(optionsCopy); foreach (var next in enumerator) { var key = CouchbaseBridge.DeserializeKey <object>(next.Key); var value = (next.Value as IEnumerable <byte>).ToArray(); var docRevision = default(RevisionInternal); if (value.Length == 1 && value[0] == 42) { docRevision = _dbStorage.GetDocument(next.DocID, null, true); } else { docRevision = _dbStorage.GetDocument(next.DocID, null, optionsCopy.IncludeDocs); } var row = new QueryRow(next.DocID, next.DocSequence, key, value, docRevision, this); if (filter != null) { if (!filter(row)) { continue; } if (skip > 0) { skip--; continue; } if (limit-- == 0) { yield break; } } Log.To.Query.V(Tag, "Query {0} found row with key={1}, value={2}, id={3}", Name, new SecureLogJsonString(key, LogMessageSensitivity.PotentiallyInsecure), new SecureLogString(value, LogMessageSensitivity.PotentiallyInsecure), new SecureLogString(next.DocID, LogMessageSensitivity.PotentiallyInsecure)); yield return(row); } }
public static void WithC4Keys(object[] keySources, bool writeNull, C4KeyActionDelegate action) { if (keySources == null) { action(null); return; } var c4Keys = new C4Key *[keySources.Length]; for (int i = 0; i < keySources.Length; i++) { if (keySources[i] == null && !writeNull) { c4Keys[i] = null; } else { c4Keys[i] = CouchbaseBridge.SerializeToKey(keySources[i]); } } try { action(c4Keys); } finally { foreach (C4Key *key in c4Keys) { Native.c4key_free(key); } } }
public IEnumerable <QueryRow> ReducedQuery(QueryOptions options) { var groupLevel = options.GroupLevel; var group = options.Group || groupLevel > 0; var reduce = Delegate == null ? null : Delegate.Reduce; if (options.ReduceSpecified) { if (!options.Reduce) { reduce = null; } else if (reduce == null) { throw Misc.CreateExceptionAndLog(Log.To.Query, StatusCode.BadParam, Tag, "Cannot use reduce option in view {0} which has no reduce block defined", Name); } } var lastKey = default(object); var filter = options.Filter; var keysToReduce = default(IList <object>); var valsToReduce = default(IList <object>); if (reduce != null) { keysToReduce = new List <object>(100); valsToReduce = new List <object>(100); } var enumerator = QueryEnumeratorWithOptions(options); var row = default(QueryRow); foreach (var next in enumerator) { var key = CouchbaseBridge.DeserializeKey <object>(next.Key); var value = default(object); if (lastKey != null && (key == null || (group && !GroupTogether(lastKey, key, groupLevel)))) { // key doesn't match lastKey; emit a grouped/reduced row for what came before: row = CreateReducedRow(lastKey, group, groupLevel, reduce, filter, keysToReduce, valsToReduce); keysToReduce.Clear(); valsToReduce.Clear(); if (row != null) { var rowCopy = row; Log.To.Query.V(Tag, "Query {0} reduced row with key={1} value={2}", Name, new SecureLogJsonString(key, LogMessageSensitivity.PotentiallyInsecure), new SecureLogJsonString(value, LogMessageSensitivity.PotentiallyInsecure)); row = null; yield return(rowCopy); } } if (key != null && reduce != null) { // Add this key/value to the list to be reduced: keysToReduce.Add(key); var nextVal = next.Value; if (nextVal.size == 1 && nextVal.ElementAt(0) == (byte)'*') { try { var rev = _dbStorage.GetDocument(next.DocID, next.DocSequence); value = rev.GetProperties(); } catch (CouchbaseLiteException e) { Log.To.Query.W(Tag, "Couldn't load doc for row value: status {0}", e.CBLStatus.Code); } catch (Exception e) { Log.To.Query.W(Tag, "Couldn't load doc for row value", e); } } else { value = Manager.GetObjectMapper().ReadValue <object>(next.Value); } valsToReduce.Add(value); } lastKey = key; } row = CreateReducedRow(lastKey, group, groupLevel, reduce, filter, keysToReduce, valsToReduce); if (row != null) { yield return(row); } }