public void OrQueries()
        {
            QueryBuilder builder = new QueryBuilder(typeof(TradeLike));

            DomainDescription domainAll = new DomainDescription(typeof(TradeLike));

            domainAll.IsFullyLoaded = true;

            OrQuery q = builder.GetManyWhere("VALUEDATE > 20100101");

            Assert.IsTrue(q.IsSubsetOf(domainAll));

            DomainDescription complexDomain = new DomainDescription(typeof(TradeLike));
            AtomicQuery       q2            = builder.MakeAtomicQuery("Folder", "AAA");
            AtomicQuery       q4            = builder.MakeAtomicQuery("ValueDate", QueryOperator.Gt, new DateTime(2001, 1, 1));

            complexDomain.AddOrReplace(q2);
            complexDomain.AddOrReplace(q4);
            OrQuery qq = builder.GetManyWhere("FOLDER = AAA, VALUEDATE > 20010101");

            Assert.IsTrue(qq.IsSubsetOf(complexDomain));

            OrQuery qqq = builder.GetManyWhere("VALUEDATE >= 20010101");

            Assert.IsFalse(qqq.IsSubsetOf(complexDomain));

            AtomicQuery q3  = builder.MakeAtomicQuery("Folder", "BBB");
            AndQuery    q33 = builder.MakeAndQuery(q3);

            qq.Elements.Add(q33);
            //the query is now (FOLDER = AAA AND VALUEDATE > 20010101) OR (FOLDER = BBB ) ans is not a subset
            //any more
            Assert.IsFalse(qq.IsSubsetOf(complexDomain));
        }
        public void AndQueries()
        {
            QueryBuilder builder = new QueryBuilder(typeof(TradeLike));

            DomainDescription domainAll = new DomainDescription(typeof(TradeLike));

            domainAll.IsFullyLoaded = true;

            //check the trivial case of a complete domain (all queries are subsets of a complete domain)
            AndQuery q1 = builder.MakeAndQuery(builder.MakeAtomicQuery("Folder", "BBB"));

            Assert.IsTrue(q1.IsSubsetOf(domainAll));

            //create a complex domain definition containing all data for Folder == AAA and for ValueDate > 20010101
            DomainDescription complexDomain = new DomainDescription(typeof(TradeLike));
            AtomicQuery       q2            = builder.MakeAtomicQuery("Folder", "AAA");
            AtomicQuery       q3            = builder.MakeAtomicQuery("Folder", "BBB");
            AtomicQuery       q4            = builder.MakeAtomicQuery("ValueDate", QueryOperator.Gt, new DateTime(2001, 1, 1));

            complexDomain.AddOrReplace(q2);
            complexDomain.AddOrReplace(q4);

            AndQuery q23 = builder.MakeAndQuery();

            q23.Elements.Add(q2);
            q23.Elements.Add(q3);

            Assert.IsTrue(q23.IsSubsetOf(complexDomain));

            AtomicQuery q5  = builder.MakeAtomicQuery("ValueDate", QueryOperator.Ge, new DateTime(2001, 1, 1));
            AndQuery    q55 = builder.MakeAndQuery(q5);

            Assert.IsFalse(q55.IsSubsetOf(complexDomain));
        }
Beispiel #3
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 = 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);

            _client.UpdateIf(newValue, orq);
        }
Beispiel #4
0
        private void VisitAndExpression(BinaryExpression binaryExpression, AndQuery andExpression)
        {
            if (IsLeafExpression(binaryExpression.Left))
            {
                andExpression.Elements.Add(VisitLeafExpression((BinaryExpression)binaryExpression.Left));
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.AndAlso)
            {
                VisitAndExpression((BinaryExpression)binaryExpression.Left, andExpression);
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.Extension)
            {
                if (binaryExpression.Left is SubQueryExpression subQuery)
                {
                    var leaf = new AtomicQuery();
                    andExpression.Elements.Add(leaf);
                    VisitContainsExpression(subQuery, leaf);
                }
            }
            else
            {
                throw new NotSupportedException("Query too complex");
            }

            if (IsLeafExpression(binaryExpression.Right))
            {
                andExpression.Elements.Add(VisitLeafExpression((BinaryExpression)binaryExpression.Right));
            }
            else if (binaryExpression.Right.NodeType == ExpressionType.Extension)
            {
                if (binaryExpression.Right is SubQueryExpression subQuery)
                {
                    var leaf = new AtomicQuery();
                    andExpression.Elements.Add(leaf);
                    VisitContainsExpression(subQuery, leaf);
                }
            }
            else
            {
                throw new NotSupportedException("Query too complex");
            }
        }
Beispiel #5
0
        public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
        {
            if (whereClause.Predicate is BinaryExpression expression)
            {
                VisitBinaryExpression(expression, RootExpression);
            }
            else
            {
                if (whereClause.Predicate is SubQueryExpression subQuery)
                {
                    AndQuery andExpression;

                    if (!RootExpression.MultipleWhereClauses)
                    {
                        andExpression = new AndQuery();
                        RootExpression.Elements.Add(andExpression);
                    }
                    else // multiple where clauses are joined by AND
                    {
                        andExpression = RootExpression.Elements[0];
                    }

                    var leaf = new AtomicQuery();
                    andExpression.Elements.Add(leaf);

                    VisitContainsExpression(subQuery, leaf);
                }
                else
                {
                    throw new NotSupportedException("Incorrect query");
                }
            }


            RootExpression.MultipleWhereClauses = true;

            base.VisitWhereClause(whereClause, queryModel, index);
        }
Beispiel #6
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);
        }
Beispiel #7
0
 public IndexRanking(IReadOnlyIndex index, AtomicQuery resolvedQuery, int ranking)
 {
     Index         = index;
     ResolvedQuery = resolvedQuery;
     Ranking       = ranking;
 }
Beispiel #8
0
        //TODO add unit test for OR expression with Contains
        /// <summary>
        ///     OR expression can be present only at root level
        /// </summary>
        /// <param name="binaryExpression"></param>
        /// <param name="rootExpression"></param>
        private void VisitOrExpression(BinaryExpression binaryExpression, OrQuery rootExpression)
        {
            // visit left part
            if (IsLeafExpression(binaryExpression.Left))
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);

                andExpression.Elements.Add(VisitLeafExpression((BinaryExpression)binaryExpression.Left));
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.AndAlso)
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);
                VisitAndExpression((BinaryExpression)binaryExpression.Left, andExpression);
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.Extension)
            {
                if (binaryExpression.Left is SubQueryExpression subQuery)
                {
                    AndQuery andExpression;

                    if (!rootExpression.MultipleWhereClauses)
                    {
                        andExpression = new AndQuery();
                        rootExpression.Elements.Add(andExpression);
                    }
                    else // multiple where clauses are joined by AND
                    {
                        andExpression = rootExpression.Elements[0];
                    }


                    var leaf = new AtomicQuery();
                    andExpression.Elements.Add(leaf);

                    VisitContainsExpression(subQuery, leaf);
                }
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.OrElse)
            {
                VisitOrExpression((BinaryExpression)binaryExpression.Left, rootExpression);
            }
            else if (binaryExpression.Left.NodeType == ExpressionType.AndAlso)
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);
                VisitAndExpression((BinaryExpression)binaryExpression.Left, andExpression);
            }
            else
            {
                throw new NotSupportedException("Query too complex");
            }

            // visit right part
            if (IsLeafExpression(binaryExpression.Right))
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);

                andExpression.Elements.Add(VisitLeafExpression((BinaryExpression)binaryExpression.Right));
            }
            else if (binaryExpression.Right.NodeType == ExpressionType.Extension)
            {
                if (binaryExpression.Right is SubQueryExpression subQuery)
                {
                    var andExpression = new AndQuery();
                    rootExpression.Elements.Add(andExpression);

                    if (rootExpression.MultipleWhereClauses)
                    {
                        throw new NotSupportedException(
                                  "Multiple where clauses can be used only with simple expressions");
                    }


                    var leaf = new AtomicQuery();
                    andExpression.Elements.Add(leaf);
                    VisitContainsExpression(subQuery, leaf);
                }
            }
            else if (binaryExpression.Right.NodeType == ExpressionType.OrElse)
            {
                VisitOrExpression((BinaryExpression)binaryExpression.Right, rootExpression);
            }
            else if (binaryExpression.Right.NodeType == ExpressionType.AndAlso)
            {
                var andExpression = new AndQuery();
                rootExpression.Elements.Add(andExpression);
                VisitAndExpression((BinaryExpression)binaryExpression.Right, andExpression);
            }
            else
            {
                throw new NotSupportedException("Query too complex");
            }
        }
Beispiel #9
0
        private void VisitContainsExpression(SubQueryExpression subQuery, AtomicQuery leaf)
        {
            if (subQuery.QueryModel.ResultOperators.Count != 1)
            {
                throw new NotSupportedException("Only Contains extension is supported");
            }

            var contains = subQuery.QueryModel.ResultOperators[0] as ContainsResultOperator;

            // process collection.Contains(x=>x.Member)
            if (contains?.Item is MemberExpression item)
            {
                var select = subQuery.QueryModel?.SelectClause.Selector as QuerySourceReferenceExpression;

                if (select?.ReferencedQuerySource is MainFromClause from)
                {
                    var expression = from.FromExpression as ConstantExpression;

                    if (expression?.Value is IEnumerable values)
                    {
                        leaf.Operator = QueryOperator.In;

                        foreach (var value in values)
                        {
                            var kval = AsKeyValue(item.Member, value);
                            leaf.InValues.Add(kval);
                        }

                        return;
                    }
                }
            }
            // process x=>x.VectorMember.Contains(value)
            else
            {
                var value = contains?.Item;

                if (value != null)
                {
                    var select = subQuery.QueryModel?.SelectClause.Selector as QuerySourceReferenceExpression;
                    var from   = select?.ReferencedQuerySource as MainFromClause;


                    if (from?.FromExpression is MemberExpression expression)
                    {
                        // the member must not be a scalar type. A string is a vector of chars but still considered a scalar in this context
                        var isVector = typeof(IEnumerable).IsAssignableFrom(expression.Type) &&
                                       !typeof(string).IsAssignableFrom(expression.Type);

                        if (!isVector)
                        {
                            throw new NotSupportedException("Trying to use Contains extension on a scalar member");
                        }


                        if (value is ConstantExpression valueExpession)
                        {
                            leaf.Operator = QueryOperator.In;

                            var kval = AsKeyValue(expression.Member, valueExpession.Value);

                            leaf.InValues.Add(kval);

                            return;
                        }
                    }
                }
            }

            throw new NotSupportedException("Only Contains extension is supported");
        }