public Boolean walkMultiExpression(MultiExpression expr) { boolean and = expr.operator == Operator.AND; Boolean res = and ? TRUE : FALSE; for (Predicate predicate : expr.predicates) { Boolean bool = bool(walkExpression(predicate)); // don't short-circuit on null, we want to walk all references deterministically if (and) { res = and(res, bool); } else { res = or(res, bool); } } return res; }
protected Integer cmp(Operand lvalue, Operand rvalue) { Object left = walkOperand(lvalue); Object right = walkOperand(rvalue); return cmp(left, right); }
public Boolean walkOr(Operand lvalue, Operand rvalue) { Boolean left = bool(walkOperand(lvalue)); Boolean right = bool(walkOperand(rvalue)); return or(left, right); }
public Boolean walkAnd(Operand lvalue, Operand rvalue) { Boolean left = bool(walkOperand(lvalue)); Boolean right = bool(walkOperand(rvalue)); return and(left, right); }
String cast = ref != null ? ref.cast : null; if (DATE_CAST.equals(cast)) { checkDateLiteralForCast(rvalue, name); return walkStartsWith(lvalue, rvalue); } else if (NXQL.ECM_PATH.equals(name)) { return walkEcmPath(op, rvalue); } else if (NXQL.ECM_ANCESTORID.equals(name)) { return walkAncestorId(op, rvalue); } else if (NXQL.ECM_ISTRASHED.equals(name)) { return walkIsTrashed(op, rvalue); } else if (name != null && name.startsWith(NXQL.ECM_FULLTEXT) && !NXQL.ECM_FULLTEXT_JOBID.equals(name)) { return walkEcmFulltext(name, op, rvalue); } else if (op == Operator.SUM) { throw new UnsupportedOperationException("SUM"); throw new UnsupportedOperationException("DIV"); } else if (op == Operator.LT) { return walkLt(lvalue, rvalue); } else if (op == Operator.GT) { return walkGt(lvalue, rvalue); } else if (op == Operator.EQ) { return walkEq(lvalue, rvalue); } else if (op == Operator.NOTEQ) { return walkNotEq(lvalue, rvalue); } else if (op == Operator.LTEQ) { return walkLtEq(lvalue, rvalue); } else if (op == Operator.GTEQ) { return walkGtEq(lvalue, rvalue);
public Boolean walkEq(Operand lvalue, Operand rvalue) { Object right = walkOperand(rvalue); if (isMixinTypes(lvalue)) { if (!(right instanceof String)) { throw new QueryParseException("Invalid EQ rhs: " + rvalue); } return walkMixinTypes(Collections.singletonList((String) right), true); } Object left = walkOperand(lvalue); return eqMaybeList(left, right); }
protected Boolean walkStartsWithNonPath(Operand lvalue, String path) { Object left = walkReference((Reference) lvalue); // exact match Boolean bool = eqMaybeList(left, path); if (TRUE.equals(bool)) { return TRUE; } // prefix match TODO escape % chars String pattern = path + "/%"; return likeMaybeList(left, pattern, true, false); }
public Boolean walkNot(Operand value) { return not(bool(walkOperand(value))); }
protected Boolean walkEcmPath(Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.NOTEQ) { throw new QueryParseException(NXQL.ECM_PATH + " requires = or <> operator"); } if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException(NXQL.ECM_PATH + " requires literal path as right argument"); } String path = ((StringLiteral) rvalue).value; if (path.length() > 1 && path.endsWith("/")) { path = path.substring(0, path.length() - 1); } String id = pathResolver.getIdForPath(path); Object right = walkReference(new Reference(NXQL.ECM_UUID)); if (id == null) { return FALSE; } Boolean eq = eq(id, right); return op == Operator.EQ ? eq : not(eq); }
protected Boolean walkEcmFulltext(String name, Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.LIKE) { throw new QueryParseException(NXQL.ECM_FULLTEXT + " requires = or LIKE operator"); } if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException(NXQL.ECM_FULLTEXT + " requires literal string as right argument"); } if (fulltextSearchDisabled) { throw new QueryParseException("Fulltext search disabled by configuration"); } String query = ((StringLiteral) rvalue).value; if (name.equals(NXQL.ECM_FULLTEXT)) { // standard fulltext query hasFulltext = true; String simple = (String) walkReference(new Reference(NXQL_ECM_FULLTEXT_SIMPLE)); String binary = (String) walkReference(new Reference(NXQL_ECM_FULLTEXT_BINARY)); return fulltext(simple, binary, query); } else { // secondary index match with explicit field // do a regexp on the field if (name.charAt(NXQL.ECM_FULLTEXT.length()) != '.') { throw new QueryParseException(name + " has incorrect syntax for a secondary fulltext index"); } String prop = name.substring(NXQL.ECM_FULLTEXT.length() + 1); String ft = query.replace(" ", "%"); rvalue = new StringLiteral(ft); return walkLike(new Reference(prop), rvalue, true, true); } }
protected Boolean like(Object left, String right, boolean caseInsensitive) { if (left == null || right == null) { return null; } if (!(left instanceof String)) { throw new QueryParseException("Invalid LIKE lhs: " + left); } String value = (String) left; if (caseInsensitive) { value = value.toLowerCase(); right = right.toLowerCase(); } String regex = likeToRegex(right); boolean match = Pattern.matches(regex.toString(), value); return match; }
private static Set<String> parseFullText(String string, int phraseSize) { if (string == null) { return Collections.emptySet(); } Set<String> set = new HashSet<>(); Deque<String> phraseWords = new LinkedList<>(); for (String word : WORD_PATTERN.split(string)) { word = parseWord(word); if (word != null) { word = word.toLowerCase(); set.add(word); if (phraseSize > 1) { phraseWords.addLast(word); if (phraseWords.size() > 1) { if (phraseWords.size() > phraseSize) { phraseWords.removeFirst(); } addPhraseWords(set, phraseWords); } } } } while (phraseWords.size() > 2) { phraseWords.removeFirst(); addPhraseWords(set, phraseWords); } return set; }
fulltext.addAll(parseFullText(string1, maxPhraseWordCount)); fulltext.addAll(parseFullText(string2, maxPhraseWordCount)); return Boolean.valueOf(fulltext(fulltext, query));
public Boolean walkLt(Operand lvalue, Operand rvalue) { Integer cmp = cmp(lvalue, rvalue); return cmp == null ? null : cmp < 0; }
public Document walkLike(Operand lvalue, Operand rvalue, boolean positive, boolean caseInsensitive) { FieldInfo fieldInfo = walkReference(lvalue); if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException("Invalid LIKE/ILIKE, right hand side must be a string: " + rvalue); } // TODO check list fields String like = walkStringLiteral((StringLiteral) rvalue); String regex = ExpressionEvaluator.likeToRegex(like); // MongoDB native matches are unanchored: optimize the regex for faster matches if (regex.startsWith(".*")) { regex = regex.substring(2); } else if (likeAnchored) { regex = "^" + regex; } if (regex.endsWith(".*")) { regex = regex.substring(0, regex.length() - 2); // better range index use } else if (likeAnchored) { regex = regex + "$"; } int flags = caseInsensitive ? Pattern.CASE_INSENSITIVE : 0; Pattern pattern = Pattern.compile(regex, flags); Object value; if (positive) { value = pattern; } else { value = new Document(QueryOperators.NOT, pattern); } return newDocumentWithField(fieldInfo, value); }
public Boolean walkGtEq(Operand lvalue, Operand rvalue) { Integer cmp = cmp(lvalue, rvalue); return cmp == null ? null : cmp >= 0; }
public Boolean walkGt(Operand lvalue, Operand rvalue) { Integer cmp = cmp(lvalue, rvalue); return cmp == null ? null : cmp > 0; }
public Boolean walkLtEq(Operand lvalue, Operand rvalue) { Integer cmp = cmp(lvalue, rvalue); return cmp == null ? null : cmp <= 0; }