コード例 #1
0
        public void TestOrQueryWithFixedPostingList_4()
        {
            var e = "{[1,1,1]}, {[1,1,3]}";

            var left  = new TermQuery(PostingListArray.Parse("[1,1,1], [1,1,3]"));
            var right = NullQuery.Instance;

            using (var q = new OrQuery(left, right))
            {
                var r = q.ExecuteToString();
                Assert.Equal(e, r);
                Assert.Null(q.NextMatch());
            }
        }
コード例 #2
0
        /// <summary>
        ///     In some cases we need the order of returned elements to be stable between calls.
        ///     For example if using the Take or Skip operators
        /// </summary>
        /// <typeparam name="TItemType"></typeparam>
        /// <param name="query"></param>
        /// <returns></returns>
        public IEnumerable <TItemType> GetMany <TItemType>(OrQuery query)

        {
            var clientResults = new IEnumerator <TItemType> [CacheClients.Count];

            try
            {
                Parallel.ForEach(CacheClients, client =>
                {
                    var resultsFromThisNode          = client.GetMany <TItemType>(query);
                    clientResults[client.ShardIndex] = resultsFromThisNode.GetEnumerator();
                });
            }
            catch (AggregateException e)
            {
                if (e.InnerException != null)
                {
                    throw e.InnerException;
                }
            }

            var count = 0;

            while (true)
            {
                var allFinished = true;
                foreach (var clientResult in clientResults)
                {
                    // limit the number of returned object if Take linq extension method was used
                    if (query.Take > 0 && count >= query.Take)
                    {
                        yield break;
                    }

                    if (clientResult.MoveNext())
                    {
                        allFinished = false;
                        yield return(clientResult.Current);

                        count++;
                    }
                }

                if (allFinished)
                {
                    yield break;
                }
            }
        }
コード例 #3
0
        public void TestOrQueryWithDefaultIndex()
        {
            using (var index = TestHelper.PrepareIndexForSearch(new PersistentIndexName(TestFolder)))
            {
                using (var query = new OrQuery(
                           new TermQuery(TestHelper.GetPostingList(index, "this")),
                           new TermQuery(TestHelper.GetPostingList(index, "is"))))
                {
                    var result   = query.ExecuteToString();
                    var expected = "{[3,1,1]}, {[3,1,2]}, {[4,1,1]}, {[4,1,4]}, {[5,1,1]}, {[6,1,2]}, {[6,1,8]}, {[6,1,9]}";

                    Assert.Equal(expected, result);
                }
            }
        }
コード例 #4
0
        /// <summary>
        ///     Count the items matching the query and check for data completeness.
        /// </summary>
        /// <param name="query"></param>
        /// <returns>completeness, items count</returns>
        public KeyValuePair <bool, int> EvalQuery(OrQuery query)
        {
            var request = new EvalRequest(query);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while getting server information", exResponse.Message,
                                         exResponse.CallStack);
            }

            var concreteResponse = (EvalResponse)response;

            return(new KeyValuePair <bool, int>(concreteResponse.Complete, concreteResponse.Items));
        }
コード例 #5
0
        public void ParsingOrQueryTest_ReturnsOrQuery()
        {
            //Arrange
            string  query    = "kiwi + banana";
            OrQuery expected = new OrQuery(
                new List <IQueryComponent> {
                new TermLiteral("kiwi"), new TermLiteral("banana")
            }
                );
            //Act
            IQueryComponent actual = parser.ParseQuery(query);

            //Assert
            actual.Should().BeOfType(typeof(OrQuery));
            ((OrQuery)actual).Components.Should().HaveSameCount(expected.Components);
        }
コード例 #6
0
        public void TestOrQueryWithFixedPostingList_1()
        {
            var e = "{[1,1,1]}, {[1,1,2]}, {[1,1,3]}, {[1,1,4]}, {[1,1,5]}, {[1,1,10]}, {[1,2,1]}, {[1,3,1]}, {[1,3,2]}, {[1,3,3]}, {[1,3,4]}, {[1,3,5]}, {[2,1,1]}, {[2,1,2]}";

            var left = new TermQuery(PostingListArray
                                     .Parse("[1,1,1], [1,1,5], [1,1,10], [1,2,1], [1,3,5], [2,1,2]"));
            var right = new TermQuery(PostingListArray
                                      .Parse("[1,1,2], [1,1,3], [1,1,4], [1,3,1], [1,3,2], [1,3,3], [1,3,4], [2,1,1]"));

            using (var q = new OrQuery(left, right))
            {
                var r = q.ExecuteToString();

                Assert.Equal(e, r);
                Assert.Null(q.NextMatch());
            }
        }
コード例 #7
0
        /// <summary>
        ///     Return cached object without deserialization to .NET object. Used to process data at json level
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public IList <CachedObject> GetObjectDescriptions(OrQuery query)
        {
            var exceptions = new List <ExceptionResponse>();
            var result     = new List <CachedObject>();
            var request    = new GetDescriptionRequest(query);

            Channel.SendStreamRequest(request, (CachedObject item, int currentItem, int totalItems) => result.Add(item),
                                      exceptions.Add);


            if (exceptions.Count > 0)
            {
                throw new CacheException("Error in GetObjectDescriptions", exceptions[0].Message,
                                         exceptions[0].CallStack);
            }

            return(result);
        }
コード例 #8
0
        public static OrQuery ToQuery(this Node node, CollectionSchema schema)
        {
            OrQuery result = null;

            if (node.Token == "select" || node.Token == "count")
            {
                result = SelectToQuery(node, schema);
            }

            QueryHelper.OptimizeQuery(result);

            if (node.Token == "count")
            {
                result !.CountOnly = true;
            }

            return(result);
        }
コード例 #9
0
        public void OrQueryRun()
        {
            var postings1 = new long[] { 1, 2, 3, 4 };
            var postings2 = new long[] { 3, 4, 5, 6 };
            var runner    = new Mock <IQueryRunner>(MockBehavior.Strict);
            var query1    = new Mock <IQuery>();

            query1.Setup(x => x.Run(runner.Object)).Returns(postings1);
            var query2 = new Mock <IQuery>();

            query2.Setup(x => x.Run(runner.Object)).Returns(postings2);

            var orQuery = new OrQuery();

            orQuery.Subqueries.Add(query1.Object);
            orQuery.Subqueries.Add(query2.Object);

            CollectionAssert.AreEquivalent(new[] { 1, 2, 3, 4, 5, 6 }, orQuery.Run(runner.Object));
        }
コード例 #10
0
ファイル: QueryVisitor.cs プロジェクト: mufeng1122/Cachalot
        private void VisitBinaryExpression(BinaryExpression binaryExpression, OrQuery rootExpression)
        {
            // manage AND expressions
            if (binaryExpression.NodeType == ExpressionType.AndAlso)
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);

                VisitAndExpression(binaryExpression, andExpression);
            }

            // manage OR expressions
            else if (binaryExpression.NodeType == ExpressionType.OrElse)
            {
                VisitOrExpression(binaryExpression, rootExpression);
            }

            // manage simple expressions like a > 10
            else if (IsLeafExpression(binaryExpression))
            {
                AndQuery andExpression;

                if (!rootExpression.MultipleWhereClauses)
                {
                    andExpression = new AndQuery();
                    rootExpression.Elements.Add(andExpression);
                }
                else // if multiple where clauses consider them as expressions linked by AND
                {
                    andExpression = rootExpression.Elements[0];
                }


                andExpression.Elements.Add(VisitLeafExpression(binaryExpression));
            }
            else
            {
                throw new NotSupportedException("Query too complex");
            }
        }
コード例 #11
0
        public int RemoveMany(OrQuery query)
        {
            var sum = 0;

            try
            {
                Parallel.ForEach(CacheClients, client =>
                {
                    var removed = client.RemoveMany(query);
                    Interlocked.Add(ref sum, removed);
                });
            }
            catch (AggregateException e)
            {
                if (e.InnerException != null)
                {
                    throw e.InnerException;
                }
            }

            return(sum);
        }
コード例 #12
0
        //TODO add unit test for timestamp synchronization (coverage)
        /// <summary>
        ///     Optimistic synchronization using a timestamp property
        ///     Works like an UpdateIf that checks the previous value of a property of type DateTime named "Timestamp"
        ///     It also updates this property withe DateTime.Now
        ///     If you use this you should never modify the timestamp manually when updating the object
        /// </summary>
        /// <param name="newValue"></param>
        public void UpdateWithTimestampSynchronization <T>(T newValue)
        {
            var prop = newValue.GetType().GetProperty("Timestamp");

            if (prop == null)
            {
                throw new CacheException($"No Timestamp property found on type {typeof(T).Name}");
            }

            if (!prop.CanWrite)
            {
                throw new CacheException($"The Timestamp property of type {typeof(T).Name} is not writable");
            }

            var oldTimestamp = prop.GetValue(newValue);

            var kv = KeyInfo.ValueToKeyValue(oldTimestamp,
                                             new KeyInfo(KeyDataType.IntKey, KeyType.ScalarIndex, "Timestamp"));

            var q        = new AtomicQuery(kv);
            var andQuery = new AndQuery();

            andQuery.Elements.Add(q);
            var orq = new OrQuery(typeof(T));

            orq.Elements.Add(andQuery);

            var now          = DateTime.Now;
            var newTimestamp = now.AddTicks(1); // add one to be sure its different


            prop.SetValue(newValue, newTimestamp);

            var packed = Pack(newValue);

            _itemsToPut.Add(packed);

            _conditions.Add(orq);
        }
コード例 #13
0
ファイル: DataClient.cs プロジェクト: usinesoft/Cachalot
        public void UpdateIf(PackedObject newValue, OrQuery testAsQuery)
        {
            if (newValue == null)
            {
                throw new ArgumentNullException(nameof(newValue));
            }


            var request = new PutRequest(testAsQuery.CollectionName)
            {
                ExcludeFromEviction = true, Predicate = testAsQuery
            };

            request.Items.Add(newValue);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while writing an object to the cache", exResponse.Message,
                                         exResponse.CallStack);
            }
        }
コード例 #14
0
        /// <summary>
        ///     remove all the items matching a query
        /// </summary>
        /// <param name="query"></param>
        /// <returns>number of items effectively removed</returns>
        public int RemoveMany(OrQuery query)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }

            var request = new RemoveManyRequest(query);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error in RemoveMany", exResponse.Message, exResponse.CallStack);
            }

            if (!(response is ItemsCountResponse countResponse))
            {
                throw new CacheException("Invalid type of response received in RemoveMany()");
            }

            return(countResponse.ItemsCount);
        }
コード例 #15
0
        public void UpdateIf <T>(T newValue, OrQuery testAsQuery)
        {
            if (newValue == null)
            {
                throw new ArgumentNullException(nameof(newValue));
            }

            CachedObject packedItem;

            if (typeof(T) == typeof(CachedObject))
            {
                packedItem = newValue as CachedObject;
            }
            else
            {
                var description = RegisterTypeIfNeeded(typeof(T));

                packedItem = CachedObject.Pack(newValue, description);
            }


            var request = new PutRequest(typeof(T))
            {
                ExcludeFromEviction = true, Predicate = testAsQuery
            };

            request.Items.Add(packedItem);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while writing an object to the cache", exResponse.Message,
                                         exResponse.CallStack);
            }
        }
コード例 #16
0
        /// <summary>
        ///     Optimistic synchronization using a timestamp property
        ///     Works like an UpdateIf that checks the previous value of a property of type DateTime named "Timestamp"
        ///     It also updates this property withe DateTime.Now
        ///     If you use this you should never modify the timestamp manually
        /// </summary>
        /// <param name="newValue"></param>
        public void UpdateWithTimestampSynchronization(T newValue)
        {
            var prop = newValue.GetType().GetProperty("Timestamp");

            if (prop == null)
            {
                throw new CacheException($"No Timestamp property found on type {typeof(T).Name}");
            }

            if (!prop.CanWrite)
            {
                throw new CacheException($"The Timestamp property of type {typeof(T).Name} is not writable");
            }

            var oldTimestamp = prop.GetValue(newValue);


            var kv = new KeyValue(oldTimestamp,
                                  new KeyInfo("Timestamp", 0, IndexType.Dictionary));

            var q        = new AtomicQuery(_collectionSchema.KeyByName(kv.KeyName), kv);
            var andQuery = new AndQuery();

            andQuery.Elements.Add(q);
            var orq = new OrQuery(_collectionName);

            orq.Elements.Add(andQuery);

            var now          = DateTime.Now;
            var newTimestamp = now.AddTicks(1); // add one to be sure its different


            prop.SetValue(newValue, newTimestamp);

            _client.UpdateIf(Pack(newValue), orq);
        }
コード例 #17
0
ファイル: PivotRequest.cs プロジェクト: usinesoft/Cachalot
 internal PivotRequest(OrQuery query)
     : base(DataAccessType.Read, query.CollectionName)
 {
     Query = query;
 }
コード例 #18
0
 // [DBFlute-0.8.9.9]
 // ===============================================================================
 //                                                                    OrScopeQuery
 //                                                                    ============
 public void OrScopeQuery(OrQuery <DmyプロシージャCB> orQuery)
 {
     xorQ((DmyプロシージャCB)this, orQuery);
 }
コード例 #19
0
        private IList <PackedObject> InternalProcessQuery(OrQuery query)
        {
            var executionPlan = new ExecutionPlan();

            try
            {
                executionPlan.Begin();

                // an empty query should return everything
                if (query.IsEmpty())
                {
                    var all = _dataStore.PrimaryIndex.GetAll().ToList();


                    if (query.OrderByProperty != null)
                    {
                        return(OrderBy(all.ToHashSet(), query.OrderByProperty, query.OrderByIsDescending, executionPlan));
                    }


                    return(all);
                }

                // simplified processing if it is an atomic query
                var atomicQuery = AsAtomic(query);

                if (atomicQuery != null)
                {
                    var res = ProcessSimpleQuery(atomicQuery, executionPlan);


                    if (query.OrderByProperty != null)
                    {
                        return(OrderBy(res.ToHashSet(), query.OrderByProperty, query.OrderByIsDescending, executionPlan));
                    }
                    else
                    {
                        return(res);
                    }
                }


                // if only one AndQuery, process sequentially
                if (query.Elements.Count == 1)
                {
                    var andQuery = query.Elements[0];

                    var set = ProcessAndQuery(andQuery, executionPlan);

                    if (query.OrderByProperty != null)
                    {
                        return(OrderBy(set.ToHashSet(), query.OrderByProperty, query.OrderByIsDescending, executionPlan));
                    }

                    return(set.ToList());
                }

                // if multiple AndQueries run in parallel
                HashSet <PackedObject> orResult = null;

                var results = new IList <PackedObject> [query.Elements.Count];

                Parallel.For(0, query.Elements.Count, i =>
                {
                    var andQuery = query.Elements[i];
                    results[i]   = ProcessAndQuery(andQuery, executionPlan);
                });

                executionPlan.BeginMerge();

                // merge the results (they may contain duplicates)
                foreach (var result in results)
                {
                    if (orResult == null)
                    {
                        orResult = new HashSet <PackedObject>(result);
                    }
                    else
                    {
                        orResult.UnionWith(result);
                    }
                }

                executionPlan.EndMerge();

                if (query.OrderByProperty != null)
                {
                    return(OrderBy(orResult, query.OrderByProperty, query.OrderByIsDescending, executionPlan));
                }


                return(orResult !.ToList());
            }
            finally
            {
                executionPlan.End();
                ExecutionPlan = executionPlan;

                _log?.LogActivity("QUERY", query.CollectionName, executionPlan.TotalTimeInMicroseconds, query.ToString(), query.Description(), executionPlan);
            }
        }
コード例 #20
0
        public void UpdateIf(PackedObject newValue, OrQuery testAsQuery)
        {
            var node = WhichNode(newValue);

            CacheClients[node].UpdateIf(newValue, testAsQuery);
        }
コード例 #21
0
        public IEnumerable <RankedItem> GetMany(OrQuery query, Guid sessionId = default)
        {
            var clientResults = new IEnumerator <RankedItem> [CacheClients.Count];

            try
            {
                Parallel.ForEach(CacheClients, client =>
                {
                    var resultsFromThisNode          = client.GetMany(query, sessionId);
                    clientResults[client.ShardIndex] = resultsFromThisNode.GetEnumerator();
                });
            }
            catch (AggregateException e)
            {
                if (e.InnerException != null)
                {
                    throw e.InnerException;
                }
            }


            HashSet <RankedItem> distinctSet = new HashSet <RankedItem>();

            // for full-text queries the order is given by the result rank
            // for normal queries order is either explicit (order by clause) or thy are unordered
            if (!query.IsFullTextQuery)
            {
                // if no order-by clause simply merge the results (in a way that guarantees a stable order between calls)
                if (query.OrderByProperty == null)
                {
                    var count = 0;
                    while (true)
                    {
                        var allFinished = true;
                        foreach (var clientResult in clientResults)
                        {
                            // limit the number of returned object if Take linq extension method was used
                            if (query.Take > 0 && count >= query.Take)
                            {
                                yield break;
                            }

                            if (clientResult.MoveNext())
                            {
                                allFinished = false;

                                var current = clientResult.Current;
                                if (query.Distinct)
                                {
                                    if (distinctSet.Add(clientResult.Current))
                                    {
                                        yield return(current);
                                    }
                                }
                                else
                                {
                                    yield return(current);
                                }

                                count++;
                            }
                        }

                        if (allFinished)
                        {
                            yield break;
                        }
                    }
                }

                // if ordered merge results by preserving order (either ascending or descending)
                foreach (var item in OrderByHelper.MixOrderedEnumerators(query.OrderByProperty, query.OrderByIsDescending, clientResults))
                {
                    yield return(item);
                }
            }
            else
            {
                // for full text queries we have to merge all results and sort by rank
                var all = new List <RankedItem>();

                Parallel.ForEach(clientResults, r =>
                {
                    List <RankedItem> resultFromClient = new List <RankedItem>();
                    while (r.MoveNext())
                    {
                        resultFromClient.Add(r.Current);
                    }

                    lock (all)
                    {
                        all.AddRange(resultFromClient);
                    }
                });

                foreach (var item in all.OrderByDescending(ri => ri.Rank))
                {
                    yield return(item);
                }
            }
        }
コード例 #22
0
 // [DBFlute-0.8.9.9]
 // ===============================================================================
 //                                                                    OrScopeQuery
 //                                                                    ============
 public void OrScopeQuery(OrQuery <Dch従業員職位履歴台帳CB> orQuery)
 {
     xorQ((Dch従業員職位履歴台帳CB)this, orQuery);
 }
コード例 #23
0
 public GetDescriptionRequest(OrQuery query)
     : base(DataAccessType.Read, query.TypeName)
 {
     Query = query;
 }
コード例 #24
0
 public GetRequest(OrQuery query)
     : base(DataAccessType.Read, query.TypeName)
 {
     _query = query;
 }
コード例 #25
0
 /// <summary>
 /// If an empty query is passed then all the data is available in the cache
 /// If a null query is passed then no domain description is available
 /// </summary>
 /// <param name="descriptionAsQuery"></param>
 /// <param name="isFullyLoaded">if true all data is available</param>
 /// <param name="description"></param>
 public DomainDescription(OrQuery descriptionAsQuery, bool isFullyLoaded = false, string description = null)
 {
     DescriptionAsQuery = descriptionAsQuery;
     IsFullyLoaded      = isFullyLoaded;
     Description        = description;
 }
コード例 #26
0
        /// <summary>
        ///     In some cases we need the order of returned elements to be stable between calls.
        ///     For example if using the Take or Skip operators
        /// </summary>
        /// <typeparam name="TItemType"></typeparam>
        /// <param name="query"></param>
        /// <returns></returns>
        public IEnumerable <TItemType> GetMany <TItemType>(OrQuery query)

        {
            var clientResults = new IEnumerator <RankedItem> [CacheClients.Count];

            try
            {
                Parallel.ForEach(CacheClients, client =>
                {
                    var resultsFromThisNode          = client.GetManyWithRank <TItemType>(query);
                    clientResults[client.ShardIndex] = resultsFromThisNode.GetEnumerator();
                });
            }
            catch (AggregateException e)
            {
                if (e.InnerException != null)
                {
                    throw e.InnerException;
                }
            }


            if (!query.IsFullTextQuery)
            {
                var count = 0;
                while (true)
                {
                    var allFinished = true;
                    foreach (var clientResult in clientResults)
                    {
                        // limit the number of returned object if Take linq extension method was used
                        if (query.Take > 0 && count >= query.Take)
                        {
                            yield break;
                        }

                        if (clientResult.MoveNext())
                        {
                            allFinished = false;
                            yield return((TItemType)clientResult.Current?.Item);

                            count++;
                        }
                    }

                    if (allFinished)
                    {
                        yield break;
                    }
                }
            }
            else // for full text queries we have to merge all results and sort by rank
            {
                var all = new List <RankedItem>();

                Parallel.ForEach(clientResults, r =>
                {
                    List <RankedItem> resultFromClient = new List <RankedItem>();
                    while (r.MoveNext())
                    {
                        resultFromClient.Add(r.Current);
                    }

                    lock (all)
                    {
                        all.AddRange(resultFromClient);
                    }
                });

                foreach (var item in all.OrderByDescending(ri => ri.Rank).Select(ri => ri.Item).Cast <TItemType>())
                {
                    yield return(item);
                }
            }
        }
コード例 #27
0
 // [DBFlute-0.8.9.9]
 // ===============================================================================
 //                                                                    OrScopeQuery
 //                                                                    ============
 public void OrScopeQuery(OrQuery <Mst従業員マスタCB> orQuery)
 {
     xorQ((Mst従業員マスタCB)this, orQuery);
 }
コード例 #28
0
 public IEnumerable <TItemType> GetMany <TItemType>(OrQuery query, bool onlyIfFullyLoaded)
 {
     return(InternalGetMany <TItemType>(query, onlyIfFullyLoaded));
 }
コード例 #29
0
 // [DBFlute-0.8.9.9]
 // ===============================================================================
 //                                                                    OrScopeQuery
 //                                                                    ============
 public void OrScopeQuery(OrQuery<Dch客室利用台帳CB> orQuery) {
     xorQ((Dch客室利用台帳CB)this, orQuery);
 }
コード例 #30
0
 /// <summary>
 ///     Retrieve multiple objects using a precompiled query.<br />
 ///     To create a valid <see cref="OrQuery" /> use a <see cref="QueryBuilder" />.
 /// </summary>
 /// <typeparam name="TItemType"></typeparam>
 /// <param name="query"></param>
 /// <returns></returns>
 public IEnumerable <TItemType> GetMany <TItemType>(OrQuery query)
 {
     return(InternalGetMany <TItemType>(query, false));
 }