in cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java [154:285]
private Node expressionNodeToSqlNode(Expression node, Expression parentNode) {
switch (node.getType()) {
case NOT_IN:
return new InNode(true);
case IN:
return new InNode(false);
case NOT_BETWEEN:
case BETWEEN:
return new BetweenNode(node.getType() == NOT_BETWEEN);
case NOT:
return new NotNode();
case BITWISE_NOT:
return new BitwiseNotNode();
case EQUAL_TO:
return new EqualNode();
case NOT_EQUAL_TO:
return new NotEqualNode();
case LIKE:
case NOT_LIKE:
case LIKE_IGNORE_CASE:
case NOT_LIKE_IGNORE_CASE:
PatternMatchNode patternMatchNode = (PatternMatchNode)node;
boolean not = node.getType() == NOT_LIKE || node.getType() == NOT_LIKE_IGNORE_CASE;
return new LikeNode(patternMatchNode.isIgnoringCase(), not, patternMatchNode.getEscapeChar());
case OBJ_PATH:
CayennePath path = (CayennePath)node.getOperand(0);
PathTranslationResult result = pathTranslator.translatePath(context.getMetadata().getObjEntity(), path);
return processPathTranslationResult(node, parentNode, result);
case DB_PATH:
CayennePath dbPath = (CayennePath)node.getOperand(0);
PathTranslationResult dbResult = pathTranslator.translatePath(context.getMetadata().getDbEntity(), dbPath);
return processPathTranslationResult(node, parentNode, dbResult);
case DBID_PATH:
CayennePath dbIdPath = (CayennePath)node.getOperand(0);
PathTranslationResult dbIdResult = pathTranslator.translateIdPath(context.getMetadata().getObjEntity(), dbIdPath);
return processPathTranslationResult(node, parentNode, dbIdResult);
case FUNCTION_CALL:
ASTFunctionCall functionCall = (ASTFunctionCall)node;
return function(functionCall.getFunctionName()).build();
case ADD:
case SUBTRACT:
case MULTIPLY:
case DIVIDE:
case BITWISE_AND:
case BITWISE_LEFT_SHIFT:
case BITWISE_OR:
case BITWISE_RIGHT_SHIFT:
case BITWISE_XOR:
case OR:
case AND:
case LESS_THAN:
case LESS_THAN_EQUAL_TO:
case GREATER_THAN:
case GREATER_THAN_EQUAL_TO:
return new OpExpressionNode(expToStr(node.getType()));
case NEGATIVE:
// we need to add minus sign as a prefix, not a separator
return new FunctionNode(expToStr(node.getType()), null, false);
case TRUE:
case FALSE:
case ASTERISK:
return new TextNode(' ' + expToStr(node.getType()));
case CUSTOM_OP:
return new OpExpressionNode(((ASTCustomOperator)node).getOperator());
case EXISTS:
return new FunctionNode("EXISTS", null, false);
case NOT_EXISTS:
return new FunctionNode("NOT EXISTS", null, false);
case ALL:
return new FunctionNode("ALL", null, false);
case ANY:
return new FunctionNode("ANY", null, false);
case SUBQUERY:
ASTSubquery subquery = (ASTSubquery)node;
DefaultSelectTranslator translator = new DefaultSelectTranslator(subquery.getQuery(), context);
translator.translate();
return translator.getContext().getSelectBuilder().build();
case ENCLOSING_OBJECT:
// Translate via parent context's translator
Expression expression = (Expression) node.getOperand(0);
if(context.getParentContext() == null) {
throw new CayenneRuntimeException("Unable to translate qualifier, no parent context to use for expression " + node);
}
expressionsToSkip.add(expression);
return context.getParentContext().getQualifierTranslator().translate(expression);
case FULL_OBJECT:
ASTFullObject fullObject = (ASTFullObject)node;
if(fullObject.getOperandCount() == 0) {
Collection<DbAttribute> dbAttributes = context.getMetadata().getDbEntity().getPrimaryKeys();
if(dbAttributes.size() > 1) {
throw new CayenneRuntimeException("Unable to translate reference on entity with more than one PK.");
}
DbAttribute attribute = dbAttributes.iterator().next();
String alias = context.getTableTree().aliasForPath(CayennePath.EMPTY_PATH);
return table(alias).column(attribute).build();
} else {
return null;
}
case SCALAR:
if (parentNode != null){
throw new CayenneRuntimeException("Incorrect state, a node %s can't have parent here", node.getClass().getName());
}
Object scalarVal = ((ASTScalar) node).getValue();
if (scalarVal instanceof Collection || scalarVal.getClass().isArray()) {
throw new CayenneRuntimeException("%s %s",ERR_MSG_ARRAYS_NOT_SUPPORTED, node.getClass().getName());
} else {
objectNode(scalarVal, null);
}
return null;
case CASE_WHEN:
return new CaseNode();
case WHEN:
return new WhenNode();
case THEN:
return new ThenNode();
case ELSE:
return new ElseNode();
}
return null;
}