/** * {@inheritDoc} * * @see * org.modeshape.jcr.query.parse.BasicSqlQueryParser#parseFrom(org.modeshape.common.text.TokenStream, * org.modeshape.jcr.query.model.TypeSystem) */ @Override protected Source parseFrom(TokenStream tokens, TypeSystem typeSystem) { Position firstSourcePosition = tokens.nextPosition(); Source source = super.parseFrom(tokens, typeSystem); if (tokens.matches(',') && source instanceof NamedSelector) { NamedSelector selector = (NamedSelector) source; JoinableSources joinedSources = new JoinableSources(selector, firstSourcePosition); while (tokens.canConsume(',')) { // This is a JCR-SQL-style JOIN ... Position nextSourcePosition = tokens.nextPosition(); NamedSelector nextSource = parseNamedSelector(tokens, typeSystem); joinedSources.add(nextSource, nextSourcePosition); } source = joinedSources; } return source; }
/** * Parse a constraint clause. This method inherits all of the functionality from JCR-SQL2, except * that JCR-SQL allows constraints that use "<code>jcr:path</code>" and "<code>jcr:score</code>" * pseudo-columns. In these special cases, the resulting {@link Comparison comparison} will have a * {@link NodePath} or {@link FullTextSearchScore} dynamic operand. * * @see * org.modeshape.jcr.query.parse.BasicSqlQueryParser#parseConstraint(org.modeshape.common.text.TokenStream, * org.modeshape.jcr.query.model.TypeSystem, org.modeshape.jcr.query.model.Source) */ @Override protected Constraint parseConstraint(TokenStream tokens, TypeSystem typeSystem, Source source) { Constraint constraint = null; if (tokens.canConsume("JCR", ":", "PATH")) { // It is a property constraint on "jcr:path" ... SelectorName selector = getSelectorNameFor(source); PropertyValue value = new PropertyValue(selector, "jcr:path"); Operator operator = parseComparisonOperator(tokens); StaticOperand right = parseStaticOperand(tokens, typeSystem); constraint = rewriteConstraint(new Comparison(value, operator, right)); } else if (tokens.matches(ANY_VALUE, "IN")) { // This is a "... 'value' IN prop ..." pattern used in the JCR TCK tests but not in the JCR // 1.0.1 specification // ... Literal value = parseLiteral(tokens, typeSystem); tokens.consume("IN"); PropertyValue propertyValue = parsePropertyValue(tokens, typeSystem, source); constraint = new SetCriteria(propertyValue, value); } else if (source instanceof JoinableSources && !(tokens.matches("(") || tokens.matches("NOT") || tokens.matches("CONTAINS", "(") || tokens.matches("ISSAMENODE", "(") || tokens.matches("ISCHILDNODE", "(") || tokens.matches("ISDESCENDANTNODE", "("))) { JoinableSources joinableSources = (JoinableSources) source; // See if this is a join condition ... if (tokens.matches(ANY_VALUE, ":", ANY_VALUE, ".", "JCR", ":", "PATH", "=") || tokens.matches(ANY_VALUE, ".", "JCR", ":", "PATH", "=")) { Position position = tokens.nextPosition(); SelectorName selector1 = parseSelectorName(tokens, typeSystem); tokens.consume('.'); parseName(tokens, typeSystem); // jcr:path tokens.consume('='); SelectorName selector2 = parseSelectorName(tokens, typeSystem); tokens.consume('.'); parseName(tokens, typeSystem); // jcr:path joinableSources.add(new SameNodeJoinCondition(selector1, selector2), position); // AND has higher precedence than OR, so we need to evaluate it first ... while (tokens.canConsume("AND")) { Constraint rhs = parseConstraint(tokens, typeSystem, source); if (rhs != null) constraint = constraint != null ? new And(constraint, rhs) : rhs; } while (tokens.canConsume("OR")) { Constraint rhs = parseConstraint(tokens, typeSystem, source); if (rhs != null) constraint = constraint != null ? new And(constraint, rhs) : rhs; } return constraint; } } if (constraint != null) { // AND has higher precedence than OR, so we need to evaluate it first ... while (tokens.canConsume("AND")) { Constraint rhs = parseConstraint(tokens, typeSystem, source); if (rhs != null) constraint = new And(constraint, rhs); } while (tokens.canConsume("OR")) { Constraint rhs = parseConstraint(tokens, typeSystem, source); if (rhs != null) constraint = new Or(constraint, rhs); } return constraint; } constraint = super.parseConstraint(tokens, typeSystem, source); constraint = rewriteConstraint(constraint); return constraint; }