示例#1
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            _queryTree.Push(new BooleanQuery());
            var visited = base.VisitLogicalPredicate(logic);

            return(visited);
        }
示例#2
0
        internal static void PrepareQuery(SnQuery query, IQueryContext context)
        {
            if (query.FiltersPrepared)
            {
                return;
            }

            var autoFiltersEnabled     = IsAutofilterEnabled(query.EnableAutofilters);
            var lifespanFiltersEnabled = IsLifespanFilterEnabled(query.EnableLifespanFilter);

            if (autoFiltersEnabled || lifespanFiltersEnabled)
            {
                var topLevelPredicate = new LogicalPredicate();
                topLevelPredicate.Clauses.Add(new LogicalClause(query.QueryTree, Occurence.Must));

                if (autoFiltersEnabled)
                {
                    topLevelPredicate.Clauses.Add(new LogicalClause(GetAutoFilterClause(context), Occurence.Must));
                }
                if (lifespanFiltersEnabled)
                {
                    topLevelPredicate.Clauses.Add(new LogicalClause(GetLifespanFilterClause(context), Occurence.Must));
                }

                query.QueryTree = topLevelPredicate;
            }

            query.FiltersPrepared = true;
        }
示例#3
0
        public static string ToString(LogicalPredicate predicate)
        {
            var visitor = new SnQueryToStringVisitor();

            visitor.VisitLogicalPredicate(predicate);
            return(visitor.Output);
        }
示例#4
0
        private SnQueryPredicate ParseQueryExpList()
        {
            // QueryExpList    ==>  QueryExp | QueryExpList QueryExp

            var queries = new List <SnQueryPredicate>();

            while (!IsEof() && _lexer.CurrentToken != CqlLexer.Token.RParen)
            {
                var q = ParseQueryExp();
                if (q != null)
                {
                    queries.Add(q);
                }
            }

            if (queries.Count == 0)
            {
                return(null);
            }

            if (queries.Count == 1)
            {
                return(queries[0]);
            }

            var boolQuery = new LogicalPredicate();

            foreach (var q in queries)
            {
                AddBooleanClause(boolQuery, q, Occurence.Default);
            }
            return(boolQuery);
        }
示例#5
0
        /* ============================================================================ Recursive descent methods */

        private SnQueryPredicate ParseTopLevelQueryExpList()
        {
            // QueryExpList    ==>  QueryExp | QueryExpList QueryExp

            var queries = new List <SnQueryPredicate>();

            while (!IsEof())
            {
                var q = ParseQueryExp();
                if (q != null)
                {
                    queries.Add(q);
                }
            }

            if (queries.Count == 0)
            {
                throw ParserError("Empty query is not allowed.");
            }

            if (queries.Count == 1)
            {
                return(queries[0]);
            }

            var boolQuery = new LogicalPredicate();

            foreach (var q in queries)
            {
                AddBooleanClause(boolQuery, q, Occurence.Default);
            }
            return(boolQuery);
        }
示例#6
0
        private static bool HasSharingRelatedClause(LogicalPredicate logicalPredicate)
        {
            var visitor = new SharingRelatedPredicateFinderVisitor();

            visitor.Visit(logicalPredicate);
            return(visitor.SharingRelatedPredicates.Count > 0);
        }
示例#7
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            // Merge clauses with sub levels if the occurences are equal.

            var visited = (LogicalPredicate)base.VisitLogicalPredicate(logic);

            var occur             = visited.Clauses[0].Occur;
            var subClausesToMerge = visited.Clauses
                                    .Where(x => x.Predicate is LogicalPredicate y && OccursAreEqual(y.Clauses[0].Occur, occur))
                                    .ToArray();

            if (subClausesToMerge.Length == 0)
            {
                return(visited);
            }

            var mergedclauses = visited.Clauses.ToList();

            foreach (var subClause in subClausesToMerge)
            {
                var subLevel = (LogicalPredicate)subClause.Predicate;
                mergedclauses.Remove(subClause);
                mergedclauses.AddRange(subLevel.Clauses);
            }

            return(new LogicalPredicate(mergedclauses));
        }
示例#8
0
        public void SnQuery_Visitor_Rewrite_CSrv()
        {
            var tree = new LogicalPredicate(
                new []
            {
                new LogicalClause(new LogicalPredicate(
                                      new [] {
                    new LogicalClause(new SimplePredicate("F1", new IndexValue("V1")), Occurence.Should),
                    new LogicalClause(new SimplePredicate("F2", new IndexValue("V2")), Occurence.Should)
                }), Occurence.Must),
                new LogicalClause(new LogicalPredicate(
                                      new [] {
                    new LogicalClause(new SimplePredicate("F3", new IndexValue("V3")), Occurence.Should),
                    new LogicalClause(new RangePredicate("F4", null, new IndexValue(10), true, true), Occurence.Should),
                }), Occurence.Must),
            });

            var visitor   = new TestVisitor();
            var rewritten = visitor.Visit(tree);

            var dumper = new SnQueryToStringVisitor();

            dumper.Visit(rewritten);

            Assert.AreEqual("+(F1:V1 F2:V2222) +(F3:V3 F4:<10)", dumper.Output);
        }
示例#9
0
 /// <summary>
 /// Replaces the top level predicate to a new LogicalPredicate that
 ///  contains the original top level predicate and a given predicate
 ///  encapsulated by two individual LogicalClause with the given occurence.
 /// </summary>
 public void AddClause(SnQueryPredicate clause, Occurence occurence)
 {
     QueryTree = new LogicalPredicate(new[]
     {
         new LogicalClause(QueryTree, occurence),
         new LogicalClause(clause, occurence),
     });
 }
示例#10
0
 public override SnQueryPredicate Visit(SnQueryPredicate predicate)
 {
     if (!_initialized)
     {
         _topLevelLogicalPredicate = predicate as LogicalPredicate;
         _initialized = true;
     }
     return(base.Visit(predicate));
 }
示例#11
0
        /// <summary>
        /// Visits the given LogicalPredicate and it's children.
        /// </summary>
        /// <param name="logic">The predicate to visit.</param>
        /// <returns>The modified predicate, if it or any child was modified; otherwise, returns the original predicate.</returns>
        public virtual SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            var clauses                = logic.Clauses;
            var visitedClauses         = VisitLogicalClauses(clauses);
            LogicalPredicate rewritten = null;

            if (visitedClauses != clauses)
            {
                rewritten = new LogicalPredicate(visitedClauses);
            }
            return(rewritten ?? logic);
        }
示例#12
0
        private static AssortedPredicates AssortPredicates(LogicalPredicate visited)
        {
            var result = new AssortedPredicates();

            foreach (var clause in visited.Clauses)
            {
                if (clause.Predicate is SimplePredicate simplePredicate)
                {
                    if (simplePredicate.FieldName == SharingVisitor.Sharing)
                    {
                        switch (clause.Occur)
                        {
                        case Occurence.Must:
                            result.SimpleMust.Add(simplePredicate);
                            break;

                        case Occurence.MustNot:
                            throw new InvalidContentSharingQueryException("Sharing related query clause cannot be negation.");
                        }
                    }
                    else
                    {
                        result.GeneralClauses.Add(clause);
                    }
                }
                else if (clause.Predicate is LogicalPredicate logicalPredicate)
                {
                    if (HasSharingRelatedClause(logicalPredicate))
                    {
                        switch (clause.Occur)
                        {
                        case Occurence.Must:
                            result.LogicalMust.Add(logicalPredicate);
                            break;

                        case Occurence.MustNot:
                            throw new InvalidContentSharingQueryException("Sharing related query clause cannot be negation.");
                        }
                    }
                    else
                    {
                        result.GeneralClauses.Add(clause);
                    }
                }
                else
                {
                    result.GeneralClauses.Add(clause);
                }
            }

            return(result);
        }
示例#13
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            var clauses        = logic.Clauses;
            var visitedClauses = VisitLogicalClauses(clauses);

            var newClauses = new List <LogicalClause>();
            var changed    = false;

            foreach (var clause in visitedClauses)
            {
                if (!(clause.Predicate is LogicalPredicate lp))
                {
                    newClauses.Add(clause);
                }
示例#14
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            if (_booleanCount++ > 0)
            {
                _output.Append("(");
            }
            var list = base.VisitLogicalPredicate(logic);

            if (--_booleanCount > 0)
            {
                _output.Append(")");
            }
            return(list);
        }
示例#15
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            var clauses        = logic.Clauses;
            var visitedClauses = VisitLogicalClauses(clauses);

            if (visitedClauses == clauses)
            {
                return(logic);
            }
            if (visitedClauses == null)
            {
                return(null);
            }
            var newList = new LogicalPredicate();

            newList.Clauses.AddRange(visitedClauses);
            return(newList);
        }
示例#16
0
        private SnQueryPredicate ParseClause()
        {
            var occur = ParseOccur();
            var query = ParseQueryExpGroup();
            var boost = ParseBoost();

            if (boost != null)
            {
                query.Boost = Convert.ToSingle(boost.Value);
            }
            if (occur == Occurence.Default || occur == Occurence.Should)
            {
                return(query);
            }
            var boolq = new LogicalPredicate();

            AddBooleanClause(boolq, query, occur);
            return(boolq);
        }
示例#17
0
        private SnQueryPredicate ParseValueClause()
        {
            // ValueClause       ==>  [Occur] ValueGroup
            var occur = ParseOccur();
            var query = ParseValueGroup();

            if (query == null)
            {
                throw ParserError("Empty clause list is not allowed: '()'.");
            }
            query.Boost = ParseBoost();
            if (occur == Occurence.Default || occur == Occurence.Should)
            {
                return(query);
            }
            var boolq = new LogicalPredicate();

            AddBooleanClause(boolq, query, occur);
            return(boolq);
        }
示例#18
0
        private SnQueryPredicate ParseUnaryNot()
        {
            var not = false;

            if (_lexer.CurrentToken == CqlLexer.Token.Not)
            {
                _lexer.NextToken();
                not = true;
            }
            var query = ParseClause();

            if (!not)
            {
                return(query);
            }
            var boolq = new LogicalPredicate();

            AddBooleanClause(boolq, query, Occurence.MustNot);
            return(boolq);
        }
示例#19
0
        private LogicalPredicate VisitTopLevelSharingPredicate(LogicalPredicate logic, bool[] isSharingFlags)
        {
            var generalClauses = new List <LogicalClause>();
            var sharingClauses = new List <LogicalClause>();

            for (int i = 0; i < logic.Clauses.Count; i++)
            {
                if (isSharingFlags[i])
                {
                    sharingClauses.Add(logic.Clauses[i]);
                }
                else
                {
                    generalClauses.Add(logic.Clauses[i]);
                }
            }

            // ---------------------------------------------------


            // Handle logical predicates
            var sharingPredicate           = new LogicalPredicate(sharingClauses);
            var normalizer                 = new SharingNormalizerVisitor();
            var normalizedSharingPredicate = normalizer.Visit(sharingPredicate);

            // Make combinations
            var composer    = new SharingComposerVisitor();
            var composition = (LogicalPredicate)composer.Visit(normalizedSharingPredicate);

            // Last normalization
            var normalizedComposition = new SharingNormalizerVisitor().Visit(composition);

            // Convert sharing combined values from string array to one comma separated string
            var finalizer = new SharingFinalizerVisitor();
            var finalTree = (LogicalPredicate)finalizer.Visit(normalizedComposition);

            // Return the final product
            var allClauses = generalClauses.Union(finalTree.Clauses);

            return(new LogicalPredicate(allClauses));
        }
示例#20
0
        private SnQueryPredicate ParseUnaryTermExp()
        {
            // UnaryTermExp      ==>  UnaryFieldHead UnaryFieldValue | ControlExp
            // UnaryFieldHead    ==>  STRING COLON | STRING NEQ
            // UnaryFieldValue   ==>  ValueGroup | Range

            var fieldInfo = _currentField.Peek();

            if (fieldInfo == null)
            {
                return(null);
            }
            if (fieldInfo.IsBinary)
            {
                return(null);
            }

            if (fieldInfo.OperatorToken == CqlLexer.Token.NEQ)
            {
                var value = ParseExactValue(true);
                var bq    = new LogicalPredicate();
                bq.Clauses.Add(new LogicalClause(CreateValueQuery(value), Occurence.MustNot));
                return(bq);
            }

            var result = ParseValueGroup();

            if (result != null)
            {
                return(result);
            }

            result = ParseRange();
            if (result != null)
            {
                return(result);
            }

            throw ParserError(String.Concat("Unexpected '", _lexer.StringValue, "'"));
        }
示例#21
0
        private SnQueryPredicate ParseValueExpList()
        {
            // ValueExpList      ==>  ValueExp | ValueExpList ValueExp

            var first = ParseValueExp();

            if (_lexer.CurrentToken == CqlLexer.Token.RParen)
            {
                return(first);
            }

            var boolQuery = new LogicalPredicate();

            AddBooleanClause(boolQuery, first, Occurence.Default);

            while (!IsEof() && _lexer.CurrentToken != CqlLexer.Token.RParen)
            {
                var q = ParseValueExp();
                AddBooleanClause(boolQuery, q, Occurence.Default);
            }

            return(boolQuery);
        }
示例#22
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            var isTopLevel = _topLevelLogicalPredicate == logic;

            var visited     = (LogicalPredicate)base.VisitLogicalPredicate(logic);
            var clauseCount = visited.Clauses.Count;

            // Get all sub-item types in righr order
            var isSharingFlags = new bool[clauseCount];

            for (var i = 0; i < clauseCount; i++)
            {
                isSharingFlags[clauseCount - i - 1] = _isSharingStack.Pop();
            }

            var isSharing = isSharingFlags.Any(x => x);
            var isMixed   = isSharingFlags.Any(x => x == !isSharingFlags[0]);

            if (isSharing && _isSharinglDisabled)
            {
                throw new InvalidContentSharingQueryException("Only one parenthesis can contain sharing related and not-sharing related clauses.");
            }

            if (!isMixed && !(isSharing && isTopLevel))
            {
                _isSharingStack.Push(isSharingFlags[0]);
                return(visited);
            }

            var visitedSharing = VisitTopLevelSharingPredicate(visited, isSharingFlags);

            _isSharinglDisabled = true;
            // push false to avoid "mixed" rank in any higher level
            _isSharingStack.Push(false);

            return(visitedSharing);
        }
示例#23
0
        private SnQueryPredicate ParseValueBinaryAnd()
        {
            // ValueBinaryAnd    ==>  ValueUnaryNot | ValueBinaryAnd AND ValueUnaryNot
            var queries = new List <SnQueryPredicate> {
                ParseValueUnaryNot()
            };

            while (_lexer.CurrentToken == CqlLexer.Token.And)
            {
                _lexer.NextToken();
                queries.Add(ParseValueUnaryNot());
            }
            if (queries.Count == 1)
            {
                return(queries[0]);
            }
            var boolq = new LogicalPredicate();

            foreach (var query in queries)
            {
                AddBooleanClause(boolq, query, Occurence.Must);
            }
            return(boolq);
        }
示例#24
0
        private SnQueryPredicate ParseBinaryOr()
        {
            // BinaryOr        ==>  BinaryAnd | BinaryOr OR BinaryAnd
            var queries = new List <SnQueryPredicate> {
                ParseBinaryAnd()
            };

            while (_lexer.CurrentToken == CqlLexer.Token.Or)
            {
                _lexer.NextToken();
                queries.Add(ParseBinaryAnd());
            }
            if (queries.Count == 1)
            {
                return(queries[0]);
            }
            var boolq = new LogicalPredicate();

            foreach (var query in queries)
            {
                AddBooleanClause(boolq, query, Occurence.Should);
            }
            return(boolq);
        }
示例#25
0
        /* ============================================================================ */

        private void AddBooleanClause(LogicalPredicate boolNode, SnQueryPredicate query, Occurence occur)
        {
            if (!(query is LogicalPredicate boolQ))
            {
                boolNode.Clauses.Add(new LogicalClause(query, occur));
                return;
            }
            var clauses = boolQ.Clauses;

            if (clauses.Count == 0)
            {
                throw ParserError("Empty BooleanNode");
            }
            if (clauses.Count > 1)
            {
                boolNode.Clauses.Add(new LogicalClause(query, occur));
                return;
            }

            // boolQ has one clause: combine occurs
            var       clause      = clauses[0];
            var       clauseOccur = clause.Occur;
            Occurence effectiveOccur;

            if (_defaultOperator == DefaultOperator.Or)
            {
                //   in  cl      eff
                //    ?  _  ==>  _
                //    ?  +  ==>  +
                //    ?  -  ==>  -
                //    _  _  ==>  _
                //    _  +  ==>  +
                //    _  -  ==>  -
                //    +  _  ==>  +
                //    +  +  ==>  +
                //    +  -  ==>  -
                //    -  _  ==>  -
                //    -  +  ==>  -
                //    -  -  ==>  -
                if (occur == Occurence.Default || occur == Occurence.Should)
                {
                    effectiveOccur = clauseOccur;
                }
                else if (occur == Occurence.MustNot)
                {
                    effectiveOccur = occur;
                }
                else if (clauseOccur == Occurence.MustNot)
                {
                    effectiveOccur = clauseOccur;
                }
                else
                {
                    effectiveOccur = occur;
                }
            }
            else
            {
                //   in  cl      eff
                //    ?  _  ==>  _
                //    ?  +  ==>  +
                //    ?  -  ==>  -
                //    _  _  ==>  _
                //    _  +  ==>  _
                //    _  -  ==>  -
                //    +  _  ==>  +
                //    +  +  ==>  +
                //    +  -  ==>  -
                //    -  _  ==>  -
                //    -  +  ==>  -
                //    -  -  ==>  -
                if (occur == Occurence.Default)
                {
                    effectiveOccur = clauseOccur;
                }
                else if (occur == Occurence.MustNot)
                {
                    effectiveOccur = occur;
                }
                else if (clauseOccur == Occurence.MustNot)
                {
                    effectiveOccur = clauseOccur;
                }
                else
                {
                    effectiveOccur = occur;
                }
            }
            clause.Occur = effectiveOccur;
            boolNode.Clauses.Add(clause);
        }
示例#26
0
 public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
 {
     _queryInfo.BooleanQueries++;
     return(base.VisitLogicalPredicate(logic));
 }
示例#27
0
        public override SnQueryPredicate VisitLogicalPredicate(LogicalPredicate logic)
        {
            var visited        = logic;
            var clauses        = logic.Clauses;
            var visitedClauses = VisitLogicalClauses(clauses);

            if (visitedClauses != clauses)
            {
                visited = new LogicalPredicate(visitedClauses);
            }


            var assortedLevel   = AssortPredicates(visited);
            var mustClauseCount = assortedLevel.SimpleMust.Count + assortedLevel.LogicalMust.Count;
            List <LogicalClause> newClauses;

            // 1 - If there are only "SHOULD" clauses or there is only one "MUST" clause, it is not necessary to do any transformation.
            //     Note that the query tree is normalized that means "MUST" clause existence excludes any "SHOULD" clause
            //     so "SHOULD" clause can only exist if the count of "MUST" clauses is 0.
            if (mustClauseCount < 2)
            {
                return(visited);
            }

            // 2 - If there are only "MUST" simple clauses but two or more: combine them and not sharing clauses be unchanged
            //     Consider that the values may already be combined.
            if (assortedLevel.SimpleMust.Count >= 2 && assortedLevel.LogicalMust.Count == 0)
            {
                newClauses = assortedLevel.GeneralClauses.ToList();

                var values = assortedLevel.SimpleMust
                             .SelectMany(x => x.Value.StringArrayValue)
                             .ToArray();

                newClauses.Add(
                    new LogicalClause(
                        CreateSharingSimplePredicate(values),
                        Occurence.Must));

                return(new LogicalPredicate(newClauses));
            }

            // 3 - If there are any "MUST" simple clauses and logical clauses: combine everything
            //     Combine all clauses for example: +a +b +(c d) +(e f) --> +(abce abcf abde abdf)
            //     In the temporary storage the inner collection stores the items of the combined values and the
            //     outer collection contains the future terms (List<List<string>>).

            // 3.1 - Combine all simple values (with breaking the already combined values)
            var combinedSimpleValues = assortedLevel.SimpleMust
                                       .SelectMany(x => x.Value.StringArrayValue).ToList();

            // 3.2 - create a temporary storage from the combined simple values.
            var combinedValues = new List <List <string> > {
                combinedSimpleValues
            };

            // 3.3 - Combine the current list with each values of each logical predicate
            foreach (var logical in assortedLevel.LogicalMust)
            {
                var values = logical.Clauses
                             .Where(x => x.Predicate is SimplePredicate)
                             .Select(x => (SimplePredicate)x.Predicate)
                             .Where(x => x.FieldName == SharingVisitor.Sharing)
                             .Select(x => x.Value.StringArrayValue.ToList())
                             .ToList();

                combinedValues = CombineValues(values, combinedValues);
            }

            // 3.4 - Create a new logical clause from the combined values
            var newPredicate       = CreateSharingLogicalPredicate(combinedValues);
            var finalSharingClause = new LogicalClause(newPredicate, Occurence.Must);

            // 3.5 - Create a list of output logical clauses.
            newClauses = assortedLevel.GeneralClauses.ToList();
            newClauses.Add(finalSharingClause);

            // 3.6 - Return with the rewritten level
            return(new LogicalPredicate(newClauses));
        }