org.eclipse.persistence.internal.jpa.parsing.JPQLParseTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2019 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.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.ModifyAllQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.UpdateAllQuery;
/**
* INTERNAL
* Purpose: This represents an EJBQL parse tre
*
Responsibilities:
* - Maintain the context for the expression generation
*
- Build an initial expression
*
- Return a reference class for the expression
*
- Maintain the root node for the query
*
* @author Jon Driscoll and Joel Lucuik
* @since TopLink 4.0
*/
public class JPQLParseTree extends ParseTree {
/**
* EJBQLParseTree constructor comment.
*/
public JPQLParseTree() {
super();
}
/**
* INTERNAL
* Build the context to be used when generating the expression from the parse tree
*/
public GenerationContext buildContext(ReadQuery readQuery, AbstractSession session) {
GenerationContext contextForGeneration = super.buildContext(readQuery, session);
contextForGeneration.setBaseQueryClass(readQuery.getReferenceClass());
return contextForGeneration;
}
/**
* INTERNAL
* Build the context to be used when generating the expression from the
* subquery parse tree.
*/
private GenerationContext buildSubqueryContext(ReadQuery readQuery, GenerationContext outer) {
GenerationContext context = new SelectGenerationContext(outer, this);
context.setBaseQueryClass(readQuery.getReferenceClass());
return context;
}
/**
* Add all of the relevant query settings from an EJBQLParseTree to the given
* database query.
* @param readQuery The query to populate
* @param outer the GenerationContext of the outer EJBQL query.
* @return the GenerationContext for the subquery
*/
public GenerationContext populateSubquery(ObjectLevelReadQuery readQuery, GenerationContext outer) {
GenerationContext innerContext = buildSubqueryContext(readQuery, outer);
populateReadQueryInternal(readQuery, innerContext);
return innerContext;
}
/**
* Add all of the relevant query settings from an EJBQLParseTree to the given
* database query.
* @param query The query to populate
* @param session The session to use to information such as descriptors.
*/
public void populateQuery(DatabaseQuery query, AbstractSession session) {
if (query.isObjectLevelReadQuery()) {
ObjectLevelReadQuery objectQuery = (ObjectLevelReadQuery)query;
GenerationContext generationContext = buildContext(objectQuery, session);
populateReadQueryInternal(objectQuery, generationContext);
} else if (query.isUpdateAllQuery()) {
UpdateAllQuery updateQuery = (UpdateAllQuery)query;
GenerationContext generationContext = buildContext(updateQuery, session);
populateModifyQueryInternal(updateQuery, generationContext);
addUpdatesToQuery(updateQuery, generationContext);
} else if (query.isDeleteAllQuery()) {
DeleteAllQuery deleteQuery = (DeleteAllQuery)query;
GenerationContext generationContext = buildContext(deleteQuery, session);
populateModifyQueryInternal(deleteQuery, generationContext);
}
}
private void populateReadQueryInternal(ObjectLevelReadQuery objectQuery,
GenerationContext generationContext) {
// Get the reference class if it does not exist. This is done
// for dynamic queries in EJBQL 3.0
if (objectQuery.getReferenceClass() == null) {
// Adjust the reference class if necessary
adjustReferenceClassForQuery(objectQuery, generationContext);
}
// Initialize the base expression in the generation context
initBaseExpression(objectQuery, generationContext);
// Validate parse tree
validate(generationContext.getSession(), getClassLoader());
// Apply the query node to the query (this will be a SelectNode for a read query)
applyQueryNodeToQuery(objectQuery, generationContext);
// Verify the SELECT is valid (valid alias, etc)
verifySelect(objectQuery, generationContext);
// This is what it's all about...
setSelectionCriteriaForQuery(objectQuery, generationContext);
// Add any ordering
addOrderingToQuery(objectQuery, generationContext);
// Add any grouping
addGroupingToQuery(objectQuery, generationContext);
// Add having
addHavingToQuery(objectQuery, generationContext);
// Add non fetch joined variables
addNonFetchJoinAttributes(objectQuery, generationContext);
}
private void populateModifyQueryInternal(ModifyAllQuery query,
GenerationContext generationContext) {
if (query.getReferenceClass() == null) {
// Adjust the reference class if necessary
adjustReferenceClassForQuery(query, generationContext);
}
query.setSession(generationContext.getSession());
// Initialize the base expression in the generation context
initBaseExpression(query, generationContext);
// Validate parse tree
validate(generationContext.getSession(), getClassLoader());
// Apply the query node to the query
applyQueryNodeToQuery(query, generationContext);
setSelectionCriteriaForQuery(query, generationContext);
}
}