blob: bdb06a6d5f0df7e3889a81e0772b2b9574939a01 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.jpa.parsing;
import org.eclipse.persistence.exceptions.JPQLException;
import org.eclipse.persistence.expressions.Expression;
/**
* INTERNAL
* <p><b>Purpose</b>: This node represents an ORDER BY item
* <p><b>Responsibilities</b>:<ul>
* <li> Generate the correct expression for ORDER BY
* </ul>
* @author Jon Driscoll
* @since OracleAS TopLink 10<i>g</i> (9.0.4)
*/
public class OrderByItemNode extends Node {
private SortDirectionNode direction = null;
private Object orderByItem = null;
private Node orderNode = null;
/**
* INTERNAL
* Validate node and calculate its type.
*/
@Override
public void validate(ParseTreeContext context) {
TypeHelper typeHelper = context.getTypeHelper();
if (orderNode == null){
if (orderByItem instanceof Node){
orderNode = (Node)orderByItem;
} else {
orderNode = context.pathForVariable((String)orderByItem);
if (orderNode == null){
throw JPQLException.nonExistantOrderByAlias(
context.getQueryInfo(), getLine(), getColumn(),
(String)orderByItem);
}
}
}
if (orderNode != null) {
orderNode.validate(context);
Object type = orderNode.getType();
setType(type);
if (!typeHelper.isOrderableType(type)) {
throw JPQLException.expectedOrderableOrderByItem(
context.getQueryInfo(), orderNode.getLine(), orderNode.getColumn(),
orderNode.getAsString(), typeHelper.getTypeName(type));
}
}
}
/** */
@Override
public Expression generateExpression(GenerationContext context) {
//BUG 3105651: Indicate to the VariableNodes in the subtree
//that they should check the SelectNode before resolving.
//If the variable involved is SELECTed, then we want an empty builder
//instead (with an empty constructor).
boolean oldCheckState = context.shouldCheckSelectNodeBeforeResolving();
((SelectGenerationContext)context).checkSelectNodeBeforeResolving(true);
Expression orderByExpression = null;
if (orderByItem instanceof Node){
orderNode = (Node)orderByItem;
orderByExpression = orderNode.generateExpression(context);
} else {
orderByExpression = context.expressionFor((String)orderByItem);
if (orderByExpression == null){
return null;
}
}
orderByExpression = getDirection().addToExpression(orderByExpression, context);
((SelectGenerationContext)context).checkSelectNodeBeforeResolving(oldCheckState);
return orderByExpression;
}
public SortDirectionNode getDirection() {
if (direction == null) {
setDirection(new SortDirectionNode());
}
return direction;
}
public Object getOrderByItem() {
return orderByItem;
}
public void setDirection(SortDirectionNode direction) {
this.direction = direction;
}
public void setOrderByItem(Object orderByItem) {
this.orderByItem = orderByItem;
}
}