use of org.apache.jackrabbit.spi.commons.query.OrderQueryNode in project jackrabbit by apache.
the class JCRSQLQueryBuilder method visit.
public Object visit(ASTOrderByClause node, Object data) {
QueryRootNode root = (QueryRootNode) data;
OrderQueryNode order = factory.createOrderQueryNode(root);
root.setOrderNode(order);
node.childrenAccept(this, order);
return root;
}
use of org.apache.jackrabbit.spi.commons.query.OrderQueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method visit.
// ---------------------< XPathVisitor >-------------------------------------
/**
* Implements the generic visit method for this <code>XPathVisitor</code>.
*
* @param node the current node as created by the XPath parser.
* @param data the current <code>QueryNode</code> created by this
* <code>XPathVisitor</code>.
* @return the current <code>QueryNode</code>. Can be different from
* <code>data</code>.
*/
public Object visit(SimpleNode node, Object data) {
QueryNode queryNode = (QueryNode) data;
switch(node.getId()) {
case JJTXPATH2:
queryNode = createPathQueryNode(node);
break;
case JJTROOT:
case JJTROOTDESCENDANTS:
if (queryNode instanceof PathQueryNode) {
((PathQueryNode) queryNode).setAbsolute(true);
} else {
exceptions.add(new InvalidQueryException("Unsupported root level query node: " + queryNode));
}
break;
case JJTSTEPEXPR:
if (isAttributeAxis(node)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION || (queryNode.getType() == QueryNode.TYPE_DEREF && ((DerefQueryNode) queryNode).getRefProperty() == null) || queryNode.getType() == QueryNode.TYPE_ORDER || queryNode.getType() == QueryNode.TYPE_PATH || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
// traverse
node.childrenAccept(this, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_NOT) {
// is null expression
RelationQueryNode isNull = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_NULL);
applyRelativePath(isNull);
node.childrenAccept(this, isNull);
NotQueryNode notNode = (NotQueryNode) queryNode;
NAryQueryNode parent = (NAryQueryNode) notNode.getParent();
parent.removeOperand(notNode);
parent.addOperand(isNull);
} else {
// not null expression
RelationQueryNode notNull = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_NOT_NULL);
applyRelativePath(notNull);
node.childrenAccept(this, notNull);
((NAryQueryNode) queryNode).addOperand(notNull);
}
} else {
if (queryNode.getType() == QueryNode.TYPE_PATH) {
createLocationStep(node, (NAryQueryNode) queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH || queryNode.getType() == QueryNode.TYPE_RELATION) {
node.childrenAccept(this, queryNode);
} else {
// step within a predicate
RelationQueryNode tmp = factory.createRelationQueryNode(null, RelationQueryNode.OPERATION_NOT_NULL);
node.childrenAccept(this, tmp);
if (tmpRelPath == null) {
tmpRelPath = new PathBuilder();
}
PathQueryNode relPath = tmp.getRelativePath();
LocationStepQueryNode[] steps = relPath.getPathSteps();
Name nameTest = steps[steps.length - 1].getNameTest();
if (nameTest == null) {
// see LocationStepQueryNode javadoc on when getNameTest()==null: when it was a star (asterisk)
nameTest = RelationQueryNode.STAR_NAME_TEST;
}
tmpRelPath.addLast(nameTest);
}
}
break;
case JJTNAMETEST:
if (queryNode.getType() == QueryNode.TYPE_LOCATION || queryNode.getType() == QueryNode.TYPE_DEREF || queryNode.getType() == QueryNode.TYPE_RELATION || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH || queryNode.getType() == QueryNode.TYPE_PATH) {
createNodeTest(node, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
// traverse
node.childrenAccept(this, queryNode);
}
break;
case JJTELEMENTNAMEORWILDCARD:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
SimpleNode child = (SimpleNode) node.jjtGetChild(0);
if (child.getId() != JJTANYNAME) {
createNodeTest(child, queryNode);
}
}
break;
case JJTTEXTTEST:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
loc.setNameTest(JCR_XMLTEXT);
}
break;
case JJTTYPENAME:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
String ntName = ((SimpleNode) node.jjtGetChild(0)).getValue();
try {
Name nt = resolver.getQName(ntName);
NodeTypeQueryNode nodeType = factory.createNodeTypeQueryNode(loc, nt);
loc.addPredicate(nodeType);
} catch (NameException e) {
exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
} catch (NamespaceException e) {
exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
}
}
break;
case JJTOREXPR:
NAryQueryNode parent = (NAryQueryNode) queryNode;
QueryNode orQueryNode = factory.createOrQueryNode(parent);
parent.addOperand(orQueryNode);
// traverse
node.childrenAccept(this, orQueryNode);
break;
case JJTANDEXPR:
parent = (NAryQueryNode) queryNode;
QueryNode andQueryNode = factory.createAndQueryNode(parent);
parent.addOperand(andQueryNode);
// traverse
node.childrenAccept(this, andQueryNode);
break;
case JJTCOMPARISONEXPR:
createExpression(node, (NAryQueryNode) queryNode);
break;
case JJTSTRINGLITERAL:
case JJTDECIMALLITERAL:
case JJTDOUBLELITERAL:
case JJTINTEGERLITERAL:
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
assignValue(node, (RelationQueryNode) queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
if (node.getId() == JJTINTEGERLITERAL) {
int index = Integer.parseInt(node.getValue());
((LocationStepQueryNode) queryNode).setIndex(index);
} else {
exceptions.add(new InvalidQueryException("LocationStep only allows integer literal as position index"));
}
} else {
exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));
}
break;
case JJTUNARYMINUS:
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setUnaryMinus(true);
} else {
exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));
}
break;
case JJTFUNCTIONCALL:
queryNode = createFunction(node, queryNode);
break;
case JJTORDERBYCLAUSE:
root.setOrderNode(factory.createOrderQueryNode(root));
queryNode = root.getOrderNode();
node.childrenAccept(this, queryNode);
break;
case JJTORDERSPEC:
OrderQueryNode orderQueryNode = (OrderQueryNode) queryNode;
orderQueryNode.newOrderSpec();
node.childrenAccept(this, queryNode);
if (!orderQueryNode.isValid()) {
exceptions.add(new InvalidQueryException("Invalid order specification. (Missing @?)"));
}
break;
case JJTORDERMODIFIER:
if (node.jjtGetNumChildren() > 0 && ((SimpleNode) node.jjtGetChild(0)).getId() == JJTDESCENDING) {
((OrderQueryNode) queryNode).setAscending(false);
}
break;
case JJTPREDICATELIST:
if (queryNode.getType() == QueryNode.TYPE_PATH) {
// switch to last location
QueryNode[] operands = ((PathQueryNode) queryNode).getOperands();
queryNode = operands[operands.length - 1];
}
node.childrenAccept(this, queryNode);
break;
case JJTPREDICATE:
if (queryNode.getType() == QueryNode.TYPE_LOCATION || queryNode.getType() == QueryNode.TYPE_DEREF) {
node.childrenAccept(this, queryNode);
} else {
// predicate not allowed here
exceptions.add(new InvalidQueryException("Unsupported location for predicate"));
}
break;
case JJTDOTDOT:
if (queryNode instanceof LocationStepQueryNode) {
((LocationStepQueryNode) queryNode).setNameTest(PATH_FACTORY.getParentElement().getName());
} else {
((RelationQueryNode) queryNode).addPathElement(PATH_FACTORY.getParentElement());
}
break;
default:
// per default traverse
node.childrenAccept(this, queryNode);
}
return queryNode;
}
use of org.apache.jackrabbit.spi.commons.query.OrderQueryNode in project jackrabbit by apache.
the class QueryImpl method execute.
/**
* Executes this query and returns a <code>{@link QueryResult}</code>.
*
* @param offset the offset in the total result set
* @param limit the maximum result size
* @return a <code>QueryResult</code>
* @throws RepositoryException if an error occurs
*/
public QueryResult execute(long offset, long limit) throws RepositoryException {
if (log.isDebugEnabled()) {
log.debug("Executing query: \n" + root.dump());
}
// build lucene query
Query query = LuceneQueryBuilder.createQuery(root, sessionContext.getSessionImpl(), index.getContext().getItemStateManager(), index.getNamespaceMappings(), index.getTextAnalyzer(), propReg, index.getSynonymProvider(), index.getIndexFormatVersion(), cache);
OrderQueryNode orderNode = root.getOrderNode();
OrderQueryNode.OrderSpec[] orderSpecs;
if (orderNode != null) {
orderSpecs = orderNode.getOrderSpecs();
} else {
orderSpecs = new OrderQueryNode.OrderSpec[0];
}
Path[] orderProperties = new Path[orderSpecs.length];
boolean[] ascSpecs = new boolean[orderSpecs.length];
String[] orderFuncs = new String[orderSpecs.length];
for (int i = 0; i < orderSpecs.length; i++) {
orderProperties[i] = orderSpecs[i].getPropertyPath();
ascSpecs[i] = orderSpecs[i].isAscending();
orderFuncs[i] = orderSpecs[i].getFunction();
}
return new SingleColumnQueryResult(index, sessionContext, this, query, new SpellSuggestion(index.getSpellChecker(), root), getColumns(), orderProperties, ascSpecs, orderFuncs, orderProperties.length == 0 && getRespectDocumentOrder(), offset, limit);
}
use of org.apache.jackrabbit.spi.commons.query.OrderQueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method createFunction.
/**
* Creates a function based on <code>node</code>.
*
* @param node the function node from the xpath tree.
* @param queryNode the current query node.
* @return the function node
*/
private QueryNode createFunction(SimpleNode node, QueryNode queryNode) {
// find out function name
String tmp = ((SimpleNode) node.jjtGetChild(0)).getValue();
String fName = tmp.substring(0, tmp.length() - 1);
try {
Name funName = resolver.getQName(fName);
if (FN_NOT.equals(funName) || FN_NOT_10.equals(funName)) {
if (queryNode instanceof NAryQueryNode) {
QueryNode not = factory.createNotQueryNode(queryNode);
((NAryQueryNode) queryNode).addOperand(not);
// @todo is this needed?
queryNode = not;
// traverse
if (node.jjtGetNumChildren() == 2) {
node.jjtGetChild(1).jjtAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("fn:not only supports one expression argument"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function fn:not"));
}
} else if (XS_DATETIME.equals(funName)) {
// check arguments
if (node.jjtGetNumChildren() == 2) {
if (queryNode instanceof RelationQueryNode) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
SimpleNode literal = (SimpleNode) node.jjtGetChild(1).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
String value = literal.getValue();
// strip quotes
value = value.substring(1, value.length() - 1);
Calendar c = ISO8601.parse(value);
if (c == null) {
exceptions.add(new InvalidQueryException("Unable to parse string literal for xs:dateTime: " + value));
} else {
rel.setDateValue(c.getTime());
}
} else {
exceptions.add(new InvalidQueryException("Wrong argument type for xs:dateTime"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function xs:dateTime"));
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for xs:dateTime"));
}
} else if (JCR_CONTAINS.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
TextsearchQueryNode contains = factory.createTextsearchQueryNode(queryNode, unescapeQuotes(literal.getValue()));
// assign property name
SimpleNode path = (SimpleNode) node.jjtGetChild(1);
path.jjtAccept(this, contains);
((NAryQueryNode) queryNode).addOperand(contains);
} else {
exceptions.add(new InvalidQueryException("Wrong argument type for jcr:contains"));
}
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for jcr:contains"));
}
} else if (JCR_LIKE.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
RelationQueryNode like = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_LIKE);
((NAryQueryNode) queryNode).addOperand(like);
// assign property name
node.jjtGetChild(1).jjtAccept(this, like);
// check property name
if (like.getRelativePath() == null) {
exceptions.add(new InvalidQueryException("Wrong first argument type for jcr:like"));
}
SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
like.setStringValue(unescapeQuotes(literal.getValue()));
} else {
exceptions.add(new InvalidQueryException("Wrong second argument type for jcr:like"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function jcr:like"));
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for jcr:like"));
}
} else if (FN_TRUE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
rel.setStringValue("true");
} else {
exceptions.add(new InvalidQueryException("Unsupported location for true()"));
}
} else if (FN_FALSE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
rel.setStringValue("false");
} else {
exceptions.add(new InvalidQueryException("Unsupported location for false()"));
}
} else if (FN_POSITION.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
if (rel.getOperation() == RelationQueryNode.OPERATION_EQ_GENERAL) {
// set dummy value to set type of relation query node
// will be overwritten when the tree is further parsed.
rel.setPositionValue(1);
rel.addPathElement(PATH_FACTORY.createElement(FN_POSITION_FULL));
} else {
exceptions.add(new InvalidQueryException("Unsupported expression with position(). Only = is supported."));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for position()"));
}
} else if (FN_FIRST.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setPositionValue(1);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
((LocationStepQueryNode) queryNode).setIndex(1);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for first()"));
}
} else if (FN_LAST.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setPositionValue(LocationStepQueryNode.LAST);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
((LocationStepQueryNode) queryNode).setIndex(LocationStepQueryNode.LAST);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for last()"));
}
} else if (JCR_DEREF.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
boolean descendant = false;
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
// remember if descendant axis
descendant = loc.getIncludeDescendants();
queryNode = loc.getParent();
((NAryQueryNode) queryNode).removeOperand(loc);
}
if (queryNode.getType() == QueryNode.TYPE_PATH) {
PathQueryNode pathNode = (PathQueryNode) queryNode;
pathNode.addPathStep(createDerefQueryNode(node, descendant, pathNode));
} else if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
DerefQueryNode deref = createDerefQueryNode(node, descendant, relNode.getRelativePath());
relNode.getRelativePath().addPathStep(deref);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for jcr:deref()"));
}
}
} else if (JCR_SCORE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_ORDER) {
setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for jcr:score()"));
}
} else if (FN_LOWER_CASE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addOperand(factory.createPropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.LOWER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(FN_LOWER_CASE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:lower-case()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for fn:lower-case()"));
}
} else if (FN_UPPER_CASE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addOperand(factory.createPropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.UPPER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(FN_UPPER_CASE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:upper-case()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for fn:upper-case()"));
}
} else if (REP_NORMALIZE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(REP_NORMALIZE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:normalize()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for rep:normalize()"));
}
} else if (REP_SIMILAR.equals(funName)) {
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
NAryQueryNode parent = (NAryQueryNode) queryNode;
RelationQueryNode rel = factory.createRelationQueryNode(parent, RelationQueryNode.OPERATION_SIMILAR);
parent.addOperand(rel);
// assign path
node.jjtGetChild(1).jjtAccept(this, rel);
// get path string
node.jjtGetChild(2).jjtAccept(this, rel);
// check if string is set
if (rel.getStringValue() == null) {
exceptions.add(new InvalidQueryException("Second argument for rep:similar() must be of type string"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:similar()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of arguments for rep:similar()"));
}
} else if (REP_SPELLCHECK.equals(funName) && queryNode.getType() != QueryNode.TYPE_PATH) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode instanceof NAryQueryNode) {
NAryQueryNode parent = (NAryQueryNode) queryNode;
RelationQueryNode rel = factory.createRelationQueryNode(parent, RelationQueryNode.OPERATION_SPELLCHECK);
parent.addOperand(rel);
// get string to check
node.jjtGetChild(1).jjtAccept(this, rel);
// check if string is set
if (rel.getStringValue() == null) {
exceptions.add(new InvalidQueryException("Argument for rep:spellcheck() must be of type string"));
}
// set a dummy property name
rel.addPathElement(PATH_FACTORY.createElement(NameConstants.JCR_PRIMARYTYPE));
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:spellcheck()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of arguments for rep:spellcheck()"));
}
} else if (queryNode.getType() == QueryNode.TYPE_RELATION) {
// use function name as name of a pseudo property in a relation
try {
Name name = resolver.getQName(fName + "()");
Path.Element element = PATH_FACTORY.createElement(name);
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addPathElement(element);
} catch (NameException e) {
exceptions.add(e);
}
} else if (queryNode.getType() == QueryNode.TYPE_PATH) {
// use function name as name of a pseudo property in select clause
try {
Name name = resolver.getQName(fName + "()");
root.addSelectProperty(name);
} catch (NameException e) {
exceptions.add(e);
}
} else {
exceptions.add(new InvalidQueryException("Unsupported function: " + fName));
}
} catch (NamespaceException e) {
exceptions.add(e);
} catch (IllegalNameException e) {
exceptions.add(e);
}
return queryNode;
}
use of org.apache.jackrabbit.spi.commons.query.OrderQueryNode in project jackrabbit by apache.
the class JCRSQLQueryBuilder method visit.
public Object visit(ASTOrderSpec node, Object data) {
OrderQueryNode order = (OrderQueryNode) data;
final Name[] identifier = new Name[1];
// collect identifier
node.childrenAccept(new DefaultParserVisitor() {
public Object visit(ASTIdentifier node, Object data) {
identifier[0] = node.getName();
return data;
}
}, data);
OrderQueryNode.OrderSpec spec = new OrderQueryNode.OrderSpec(identifier[0], true);
order.addOrderSpec(spec);
node.childrenAccept(this, spec);
return data;
}
Aggregations