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); }