Example #1
0
        protected internal virtual FullTextQuery conjunction(QueryScanner scanner)
        {
            FullTextQuery left = term(scanner);

            if (scanner.token == QueryScanner.TKN_WORD || scanner.token == QueryScanner.TKN_AND)
            {
                if (scanner.token == QueryScanner.TKN_WORD)
                {
                    scanner.unget = true;
                }
                FullTextQuery.Operator cop   = scanner.inQuotes ? FullTextQuery.Operator.Near : FullTextQuery.Operator.And;
                FullTextQuery          right = disjunction(scanner);
                if (left != null && right != null)
                {
                    return(new FullTextQueryBinaryOp(cop, left, right));
                }
                else if (right != null)
                {
                    return(right);
                }
            }
            return(left);
        }
            internal virtual FullTextQuery optimize(FullTextQuery query)
            {
                switch (query.op)
                {
                case FullTextQuery.Operator.And:
                case FullTextQuery.Operator.Near:
                {
                    FullTextQuery.Operator op = query.op;
                    int           nConjuncts  = 1;
                    FullTextQuery q           = query;
                    while ((q = ((FullTextQueryBinaryOp)q).right).op == op)
                    {
                        nConjuncts += 1;
                    }
                    ExpressionWeight[] conjuncts = new ExpressionWeight[nConjuncts + 1];
                    q = query;
                    for (int i = 0; i < nConjuncts; i++)
                    {
                        FullTextQueryBinaryOp and = (FullTextQueryBinaryOp)q;
                        conjuncts[i]        = new ExpressionWeight();
                        conjuncts[i].expr   = optimize(and.left);
                        conjuncts[i].weight = calculateWeight(conjuncts[i].expr);
                        q = and.right;
                    }
                    conjuncts[nConjuncts]        = new ExpressionWeight();
                    conjuncts[nConjuncts].expr   = optimize(q);
                    conjuncts[nConjuncts].weight = calculateWeight(conjuncts[nConjuncts].expr);
                    Array.Sort(conjuncts);
                    if (op == FullTextQuery.Operator.And)
                    {
                        // eliminate duplicates
                        int         n = 0, j = -1;
                        InverseList list = null;
                        for (int i = 0; i <= nConjuncts; i++)
                        {
                            q = conjuncts[i].expr;
                            if (q is FullTextQueryMatchOp)
                            {
                                FullTextQueryMatchOp match = (FullTextQueryMatchOp)q;
                                if (n == 0 || kwds[match.wno].list != list)
                                {
                                    j              = match.wno;
                                    list           = kwds[j].list;
                                    conjuncts[n++] = conjuncts[i];
                                }
                                else
                                {
                                    kwds[match.wno].sameAs = j;
                                }
                            }
                            else
                            {
                                conjuncts[n++] = conjuncts[i];
                            }
                        }
                        nConjuncts = n - 1;
                    }
                    else
                    {
                        // calculate distance between keywords
                        int kwdPos = 0;
                        for (int i = 0; i <= nConjuncts; i++)
                        {
                            q = conjuncts[i].expr;
                            if (q is FullTextQueryMatchOp)
                            {
                                FullTextQueryMatchOp match = (FullTextQueryMatchOp)q;
                                kwds[match.wno].kwdOffset = match.pos - kwdPos;
                                kwdPos = match.pos;
                            }
                        }
                    }
                    if (nConjuncts == 0)
                    {
                        return(conjuncts[0].expr);
                    }
                    else
                    {
                        q = query;
                        int i = 0;
                        while (true)
                        {
                            FullTextQueryBinaryOp and = (FullTextQueryBinaryOp)q;
                            and.left = conjuncts[i].expr;
                            if (++i < nConjuncts)
                            {
                                q = and.right;
                            }
                            else
                            {
                                and.right = conjuncts[i].expr;
                                break;
                            }
                        }
                    }
                    break;
                }

                case FullTextQuery.Operator.Or:
                {
                    FullTextQueryBinaryOp or = (FullTextQueryBinaryOp)query;
                    or.left  = optimize(or.left);
                    or.right = optimize(or.right);
                    break;
                }

                case FullTextQuery.Operator.Not:
                {
                    FullTextQueryUnaryOp not = (FullTextQueryUnaryOp)query;
                    not.opd = optimize(not.opd);
                }
                break;

                default:;
                    break;
                }
                return(query);
            }