Search in sources :

Example 1 with QueryOptions

use of org.apache.jackrabbit.oak.query.QueryOptions in project jackrabbit-oak by apache.

the class XPathToSQL2Converter method convertToUnion.

private Statement convertToUnion(String query, Statement statement, int startParseIndex) throws ParseException {
    int start = query.indexOf("(", startParseIndex);
    String begin = query.substring(0, start);
    XPathToSQL2Converter converter = new XPathToSQL2Converter();
    String partList = query.substring(start);
    converter.initialize(partList);
    converter.read();
    int lastParseIndex = converter.parseIndex;
    int lastOrIndex = lastParseIndex;
    converter.read("(");
    int level = 0;
    ArrayList<String> parts = new ArrayList<String>();
    int parseIndex;
    while (true) {
        parseIndex = converter.parseIndex;
        if (converter.readIf("(")) {
            level++;
        } else if (converter.readIf(")")) {
            if (level-- <= 0) {
                break;
            }
        } else if (converter.readIf("|") && level == 0) {
            String or = partList.substring(lastOrIndex, parseIndex - 1);
            parts.add(or);
            lastOrIndex = parseIndex;
        } else if (converter.currentTokenType == END) {
            throw getSyntaxError("empty query or missing ')'");
        } else {
            converter.read();
        }
    }
    String or = partList.substring(lastOrIndex, parseIndex - 1);
    parts.add(or);
    String end = partList.substring(parseIndex);
    Statement result = null;
    ArrayList<Order> orderList = null;
    QueryOptions queryOptions = null;
    for (String p : parts) {
        String q = begin + p + end;
        converter = new XPathToSQL2Converter();
        Statement stat = converter.convertToStatement(q);
        orderList = stat.orderList;
        queryOptions = stat.queryOptions;
        // reset fields that are used in the union,
        // but no longer in the individual statements
        // (can not use clear, because it is shared)
        stat.orderList = new ArrayList<Order>();
        stat.queryOptions = null;
        if (result == null) {
            result = stat;
        } else {
            UnionStatement union = new UnionStatement(result, stat);
            result = union;
        }
    }
    result.orderList = orderList;
    result.queryOptions = queryOptions;
    result.setExplain(statement.explain);
    result.setMeasure(statement.measure);
    return result;
}
Also used : UnionStatement(org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement) ArrayList(java.util.ArrayList) QueryOptions(org.apache.jackrabbit.oak.query.QueryOptions) UnionStatement(org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement)

Example 2 with QueryOptions

use of org.apache.jackrabbit.oak.query.QueryOptions in project jackrabbit-oak by apache.

the class XPathToSQL2Converter method convertToStatement.

private Statement convertToStatement(String query) throws ParseException {
    query = query.trim();
    Statement statement = new Statement();
    if (query.startsWith("explain ")) {
        query = query.substring("explain".length()).trim();
        statement.setExplain(true);
    }
    if (query.startsWith("measure")) {
        query = query.substring("measure".length()).trim();
        statement.setMeasure(true);
    }
    if (query.isEmpty()) {
        // special case, will always result in an empty result
        query = "//jcr:root";
    }
    statement.setOriginalQuery(query);
    initialize(query);
    expected = new ArrayList<String>();
    read();
    if (currentTokenType == END) {
        throw getSyntaxError("the query may not be empty");
    }
    currentSelector.name = "a";
    String pathPattern = "";
    boolean startOfQuery = true;
    while (true) {
        // if true, path or nodeType conditions are not allowed
        boolean shortcut = false;
        boolean slash = readIf("/");
        if (!slash) {
            if (startOfQuery) {
                // the query doesn't start with "/"
                currentSelector.path = "/";
                pathPattern = "/";
                currentSelector.isChild = true;
            } else {
                break;
            }
        } else if (readIf("jcr:root")) {
            // "/jcr:root" may only appear at the beginning
            if (!pathPattern.isEmpty()) {
                throw getSyntaxError("jcr:root needs to be at the beginning");
            }
            if (readIf("/")) {
                // "/jcr:root/"
                currentSelector.path = "/";
                pathPattern = "/";
                if (readIf("/")) {
                    // "/jcr:root//"
                    pathPattern = "//";
                    currentSelector.isDescendant = true;
                } else {
                    currentSelector.isChild = true;
                }
            } else {
                // for example "/jcr:root[condition]"
                pathPattern = "/%";
                currentSelector.path = "/";
                shortcut = true;
            }
        } else if (readIf("/")) {
            // "//" was read
            pathPattern += "%";
            if (currentSelector.isDescendant) {
                // the query started with "//", and now "//" was read
                nextSelector(true);
            }
            currentSelector.isDescendant = true;
        } else {
            // the token "/" was read
            pathPattern += "/";
            if (startOfQuery) {
                currentSelector.path = "/";
            } else {
                if (currentSelector.isDescendant) {
                    // the query started with "//", and now "/" was read
                    nextSelector(true);
                }
                currentSelector.isChild = true;
            }
        }
        int startParseIndex = parseIndex;
        if (shortcut) {
        // "*" and so on are not allowed now
        } else if (readIf("*")) {
            // "...*"
            pathPattern += "%";
            if (!currentSelector.isDescendant) {
                if (selectors.size() == 0 && currentSelector.path.equals("")) {
                    // the query /* is special
                    currentSelector.path = "/";
                }
            }
        } else if (currentTokenType == IDENTIFIER) {
            // probably a path restriction
            // String name = readPathSegment();
            String identifier = readIdentifier();
            if (readIf("(")) {
                if ("text".equals(identifier)) {
                    // "...text()"
                    currentSelector.isChild = false;
                    pathPattern += "jcr:xmltext";
                    read(")");
                    if (currentSelector.isDescendant) {
                        currentSelector.nodeName = "jcr:xmltext";
                    } else {
                        currentSelector.path = PathUtils.concat(currentSelector.path, "jcr:xmltext");
                    }
                } else if ("element".equals(identifier)) {
                    // "...element(..."
                    if (readIf(")")) {
                        // any
                        pathPattern += "%";
                    } else {
                        if (readIf("*")) {
                            // any
                            pathPattern += "%";
                        } else {
                            String name = readPathSegment();
                            pathPattern += name;
                            appendNodeName(name);
                        }
                        if (readIf(",")) {
                            currentSelector.nodeType = readIdentifier();
                        }
                        read(")");
                    }
                } else if ("rep:excerpt".equals(identifier)) {
                    Expression.Property p;
                    if (readIf(".")) {
                        rewindSelector();
                        p = new Expression.Property(currentSelector, "rep:excerpt", false);
                    } else {
                        // this will also deal with relative properties
                        Expression e = parseExpression();
                        if (!(e instanceof Expression.Property)) {
                            throw getSyntaxError();
                        }
                        Expression.Property prop = (Expression.Property) e;
                        String property = prop.getColumnAliasName();
                        rewindSelector();
                        p = new Expression.Property(currentSelector, "rep:excerpt(" + property + ")", false);
                    }
                    read(")");
                    statement.addSelectColumn(p);
                } else {
                    throw getSyntaxError();
                }
            } else {
                String name = ISO9075.decode(identifier);
                pathPattern += name;
                appendNodeName(name);
            }
        } else if (readIf("@")) {
            rewindSelector();
            Expression.Property p = readProperty();
            statement.addSelectColumn(p);
        } else if (readIf("(")) {
            rewindSelector();
            do {
                if (readIf("@")) {
                    Expression.Property p = readProperty();
                    statement.addSelectColumn(p);
                } else if (readIf("rep:excerpt")) {
                    Expression.Property p;
                    read("(");
                    if (readIf(".")) {
                        p = new Expression.Property(currentSelector, "rep:excerpt", false);
                    } else {
                        // this will also deal with relative properties
                        Expression e = parseExpression();
                        if (!(e instanceof Expression.Property)) {
                            throw getSyntaxError();
                        }
                        Expression.Property prop = (Expression.Property) e;
                        String property = prop.getColumnAliasName();
                        p = new Expression.Property(currentSelector, "rep:excerpt(" + property + ")", false);
                    }
                    read(")");
                    statement.addSelectColumn(p);
                } else if (readIf("rep:spellcheck")) {
                    // only rep:spellcheck() is currently supported
                    read("(");
                    read(")");
                    Expression.Property p = new Expression.Property(currentSelector, "rep:spellcheck()", false);
                    statement.addSelectColumn(p);
                } else if (readIf("rep:suggest")) {
                    readOpenDotClose(true);
                    Expression.Property p = new Expression.Property(currentSelector, "rep:suggest()", false);
                    statement.addSelectColumn(p);
                } else if (readIf("rep:facet")) {
                    // this will also deal with relative properties
                    // (functions and so on are also working, but this is probably not needed)
                    read("(");
                    Expression e = parseExpression();
                    if (!(e instanceof Expression.Property)) {
                        throw getSyntaxError();
                    }
                    Expression.Property prop = (Expression.Property) e;
                    String property = prop.getColumnAliasName();
                    read(")");
                    rewindSelector();
                    Expression.Property p = new Expression.Property(currentSelector, "rep:facet(" + property + ")", false);
                    statement.addSelectColumn(p);
                }
            } while (readIf("|"));
            if (!readIf(")")) {
                return convertToUnion(query, statement, startParseIndex - 1);
            }
        } else if (readIf(".")) {
            // "a/./b" is the same as "a/b"
            if (readIf(".")) {
                // ".." means "the parent of the node"
                // handle like a regular path restriction
                String name = "..";
                pathPattern += name;
                if (!currentSelector.isChild) {
                    currentSelector.nodeName = name;
                } else {
                    if (currentSelector.isChild) {
                        currentSelector.isChild = false;
                        currentSelector.isParent = true;
                    }
                }
            } else {
                if (selectors.size() > 0) {
                    currentSelector = selectors.remove(selectors.size() - 1);
                    currentSelector.condition = null;
                    currentSelector.joinCondition = null;
                }
            }
        } else {
            throw getSyntaxError();
        }
        if (readIf("[")) {
            do {
                Expression c = parseConstraint();
                currentSelector.condition = Expression.and(currentSelector.condition, c);
                read("]");
            } while (readIf("["));
        }
        startOfQuery = false;
        nextSelector(false);
    }
    if (selectors.size() == 0) {
        nextSelector(true);
    }
    // the current selector wasn't used so far
    // go back to the last one
    currentSelector = selectors.get(selectors.size() - 1);
    if (selectors.size() == 1) {
        currentSelector.onlySelector = true;
    }
    if (readIf("order")) {
        read("by");
        do {
            Order order = new Order();
            order.expr = parseExpression();
            if (readIf("descending")) {
                order.descending = true;
            } else {
                readIf("ascending");
            }
            statement.addOrderBy(order);
        } while (readIf(","));
    }
    QueryOptions options = null;
    if (readIf("option")) {
        read("(");
        options = new QueryOptions();
        while (true) {
            if (readIf("traversal")) {
                String type = readIdentifier().toUpperCase(Locale.ENGLISH);
                options.traversal = Traversal.valueOf(type);
            } else if (readIf("index")) {
                if (readIf("name")) {
                    options.indexName = readIdentifier();
                } else if (readIf("tag")) {
                    options.indexTag = readIdentifier();
                }
            } else {
                break;
            }
            readIf(",");
        }
        read(")");
    }
    if (!currentToken.isEmpty()) {
        throw getSyntaxError("<end>");
    }
    statement.setColumnSelector(currentSelector);
    statement.setSelectors(selectors);
    statement.setQueryOptions(options);
    Expression where = null;
    for (Selector s : selectors) {
        where = Expression.and(where, s.condition);
    }
    statement.setWhere(where);
    return statement;
}
Also used : UnionStatement(org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement) QueryOptions(org.apache.jackrabbit.oak.query.QueryOptions)

Example 3 with QueryOptions

use of org.apache.jackrabbit.oak.query.QueryOptions in project jackrabbit-oak by apache.

the class SelectorImpl method createFilter.

/**
 * Create the filter condition for planning or execution.
 *
 * @param preparing whether a filter for the prepare phase should be made
 * @return the filter
 */
@Override
public FilterImpl createFilter(boolean preparing) {
    FilterImpl f = new FilterImpl(this, query.getStatement(), query.getSettings());
    f.setPreparing(preparing);
    if (joinCondition != null) {
        joinCondition.restrict(f);
    }
    // we will need the excerpt
    for (ColumnImpl c : query.getColumns()) {
        if (c.getSelector().equals(this)) {
            String columnName = c.getColumnName();
            if (columnName.equals(QueryConstants.OAK_SCORE_EXPLANATION)) {
                f.restrictProperty(columnName, Operator.NOT_EQUAL, null);
            } else if (columnName.startsWith(QueryConstants.REP_EXCERPT)) {
                f.restrictProperty(QueryConstants.REP_EXCERPT, Operator.EQUAL, PropertyValues.newString(columnName));
            } else if (columnName.startsWith(QueryConstants.REP_FACET)) {
                f.restrictProperty(QueryConstants.REP_FACET, Operator.EQUAL, PropertyValues.newString(columnName));
            }
        }
    }
    // (".. is null" must be written as "not .. is not null").
    if (queryConstraint != null) {
        queryConstraint.restrict(f);
        FullTextExpression ft = queryConstraint.getFullTextConstraint(this);
        f.setFullTextConstraint(ft);
    }
    for (ConstraintImpl constraint : selectorConstraints) {
        constraint.restrict(f);
    }
    QueryOptions options = query.getQueryOptions();
    if (options != null) {
        if (options.indexName != null) {
            f.restrictProperty(IndexConstants.INDEX_NAME_OPTION, Operator.EQUAL, PropertyValues.newString(options.indexName));
        }
        if (options.indexTag != null) {
            f.restrictProperty(IndexConstants.INDEX_TAG_OPTION, Operator.EQUAL, PropertyValues.newString(options.indexTag));
        }
    }
    return f;
}
Also used : FilterImpl(org.apache.jackrabbit.oak.query.index.FilterImpl) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression) QueryOptions(org.apache.jackrabbit.oak.query.QueryOptions)

Aggregations

QueryOptions (org.apache.jackrabbit.oak.query.QueryOptions)3 UnionStatement (org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement)2 ArrayList (java.util.ArrayList)1 FilterImpl (org.apache.jackrabbit.oak.query.index.FilterImpl)1 FullTextExpression (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression)1