![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.persistence.jpa.jpql.parser.AsOfClause 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 346465e
/*
* Copyright (c) 2012, 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
//
package org.eclipse.persistence.jpa.jpql.parser;
import java.util.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;
/**
* An AS OF
clause is part of a flashback query, which provides ways to view
* past states of database objects, or to return database objects to a previous state, without using
* traditional point-in-time recovery.
*
* Specify AS OF
to retrieve the single version of the rows returned by the
* query at a particular change number (SCN) or timestamp. If you specify SCN, then the expression
* must evaluate to a number. If you specify TIMESTAMP
, then the expression must
* evaluate to a timestamp value. Oracle Database returns rows as they existed at the specified
* system change number or time.
*
* BNF: asof_clause ::= AS OF { SCN | TIMESTAMP } scalar_expression
*
* @version 2.5
* @since 2.5
* @author Pascal Filion
*/
public final class AsOfClause extends AbstractExpression {
/**
* The {@link Expression} representing the timestamp or change number.
*/
private AbstractExpression expression;
/**
* Determines whether a whitespace was found after either SCN
or
* TIMESTAMP
.
*/
private boolean hasSpaceAfterCategory;
/**
* Determines whether a whitespace was found after AS OF
.
*/
private boolean hasSpaceAfterIdentifier;
/**
* The actual identifier found in the string representation of the JPQL query.
*/
private String identifier;
/**
* The actual SCN
identifier found in the string representation of the
* JPQL query.
*/
private String scnIdentifier;
/**
* The actual TIMESTAMP
identifier found in the string representation of the
* JPQL query.
*/
private String timestampIdentifier;
/**
* Creates a new AsOfClause
.
*
* @param parent The parent of this expression
*/
public AsOfClause(AbstractExpression parent) {
super(parent, AS_OF);
}
@Override
public void accept(ExpressionVisitor visitor) {
acceptUnknownVisitor(visitor);
}
@Override
public void acceptChildren(ExpressionVisitor visitor) {
getExpression().accept(visitor);
}
@Override
protected void addChildrenTo(Collection children) {
children.add(getExpression());
}
@Override
protected void addOrderedChildrenTo(List children) {
// 'AS OF'
children.add(buildStringExpression(AS_OF));
if (hasSpaceAfterIdentifier) {
children.add(buildStringExpression(SPACE));
}
// 'SCN'
if (scnIdentifier != null) {
children.add(buildStringExpression(SCN));
}
// 'TIMESTAMP'
else if (timestampIdentifier != null) {
children.add(buildStringExpression(TIMESTAMP));
}
if (hasSpaceAfterCategory) {
children.add(buildStringExpression(SPACE));
}
// Expression
if (expression != null) {
children.add(expression);
}
}
@Override
public JPQLQueryBNF findQueryBNF(Expression expression) {
if ((this.expression != null) && this.expression.isAncestor(expression)) {
return getQueryBNF(ScalarExpressionBNF.ID);
}
return super.findQueryBNF(expression);
}
/**
* Returns the actual AS OF identifier found in the string representation of the JPQL
* query, which has the actual case that was used.
*
* @return The AS OF identifier that was actually parsed
*/
public String getActualIdentifier() {
return identifier;
}
/**
* Returns the actual SCN identifier found in the string representation of the JPQL query,
* which has the actual case that was used.
*
* @return The SCN identifier that was actually parsed, or an empty string if it was not parsed
*/
public String getActualScnIdentifier() {
return (scnIdentifier != null) ? scnIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the actual TIMESTAMP identifier found in the string representation of the JPQL
* query, which has the actual case that was used.
*
* @return The TIMESTAMP identifier that was actually parsed, or an empty string if it was
* not parsed
*/
public String getActualTimestampIdentifier() {
return (timestampIdentifier != null) ? timestampIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the {@link Expression} representing the timestamp or change number.
*
* @return The {@link Expression} that was parsed representing the timestamp or change number
*/
public Expression getExpression() {
if (expression == null) {
expression = buildNullExpression();
}
return expression;
}
@Override
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(AsOfClauseBNF.ID);
}
/**
* Determines whether the {@link Expression} representing the timestamp or change number was
* parsed or not.
*
* @return true
if the timestamp or change number was parsed; false
otherwise
*/
public boolean hasExpression() {
return expression != null &&
!expression.isNull();
}
/**
* Determines whether the identifier SCN was part of the query.
*
* @return true
if the identifier SCN was parsed; false
otherwise
*/
public boolean hasScn() {
return scnIdentifier != null;
}
/**
* Determines whether a whitespace was found after either SCN or TIMESTAMP
.
*
* @return true
if there was a whitespace after SCN or TIMESTAMP
;
* false
otherwise
*/
public boolean hasSpaceAfterCategory() {
return hasSpaceAfterCategory;
}
/**
* Determines whether a whitespace was found after AS OF.
*
* @return true
if there was a whitespace after AS OF; false
otherwise
*/
public boolean hasSpaceAfterIdentifier() {
return hasSpaceAfterIdentifier;
}
/**
* Determines whether the identifier TIMESTAMP was part of the query.
*
* @return true
if the identifier TIMESTAMP was parsed; false
otherwise
*/
public boolean hasTimestamp() {
return timestampIdentifier != null;
}
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
// 'AS OF'
identifier = wordParser.moveForwardIgnoreWhitespace(AS_OF);
hasSpaceAfterIdentifier = wordParser.skipLeadingWhitespace() > 0;
// 'SCN'
if (wordParser.startsWithIdentifier(SCN)) {
scnIdentifier = wordParser.moveForward(SCN);
hasSpaceAfterCategory = wordParser.skipLeadingWhitespace() > 0;
}
// 'TIMESTAMP'
else if (wordParser.startsWithIdentifier(TIMESTAMP)) {
timestampIdentifier = wordParser.moveForward(TIMESTAMP);
hasSpaceAfterCategory = wordParser.skipLeadingWhitespace() > 0;
}
// Expression
expression = parse(wordParser, ScalarExpressionBNF.ID, tolerant);
}
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
// 'AS OF'
writer.append(actual ? identifier : AS_OF);
if (hasSpaceAfterIdentifier) {
writer.append(SPACE);
}
// 'SCN'
if (scnIdentifier != null) {
writer.append(actual ? scnIdentifier : SCN);
}
// 'TIMESTAMP'
if (timestampIdentifier != null) {
writer.append(actual ? timestampIdentifier : TIMESTAMP);
}
if (hasSpaceAfterCategory) {
writer.append(SPACE);
}
// Expression
if (expression != null) {
expression.toParsedText(writer, actual);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy