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