blob: f3868992a3b7a268885de0cb7d3fe4d513a2be59 [file] [log] [blame]
/*
* Copyright (c) 1998, 2020 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.expressions;
import java.util.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
/**
* <b>Purpose:</b>Represents The FOR UPDATE OF fine-grained pessimistically
* locking clause.
* @author Stephen McRitchie
* @since Oracle Toplink 10g AS
*/
public class ForUpdateOfClause extends ForUpdateClause {
protected List<Expression> lockedExpressions;
public ForUpdateOfClause() {
}
public void addLockedExpression(ObjectExpression expression) {
getLockedExpressions().add(expression);
}
public void addLockedExpression(FieldExpression expression) {
getLockedExpressions().add(expression);
}
public List<Expression> getLockedExpressions() {
if (lockedExpressions == null) {
lockedExpressions = new ArrayList();
}
return lockedExpressions;
}
@Override
public boolean isForUpdateOfClause() {
return true;
}
@Override
public boolean isReferenceClassLocked() {
if (this.lockedExpressions == null) {
return false;
}
// Normally the expressionBuilder is stored first but not necessarily
// when a child ForUpdateOfClause is built for a nested query, or if a
//user made this clause.
int size = this.lockedExpressions.size();
for (int i = 0; i < size; i++) {
if (this.lockedExpressions.get(i).isExpressionBuilder()) {
return true;
}
}
return false;
}
public void setLockedExpressions(List<Expression> lockedExpressions) {
this.lockedExpressions = lockedExpressions;
}
public void setLockMode(short lockMode) {
this.lockMode = lockMode;
}
/**
* INTERNAL:
* Prints the as of clause for an expression inside of the FROM clause.
*/
@Override
public void printSQL(ExpressionSQLPrinter printer, SQLSelectStatement statement) {
// assert(lockedExpressions != null && lockedExpressions.size() > 0);
// assert( getLockMode() == ObjectBuildingQuery.LOCK ||
// getLockMode() == ObjectBuildingQuery.LOCK_NOWAIT);
if(printer.getSession().getPlatform().shouldPrintLockingClauseAfterWhereClause()) {
ExpressionBuilder clonedBuilder = statement.getBuilder();
printer.printString(printer.getSession().getPlatform().getSelectForUpdateOfString());
printer.setIsFirstElementPrinted(false);
for (Expression next : getLockedExpressions()) {
// Necessary as this was determined in query framework.
next = next.rebuildOn(clonedBuilder);
if(next.isObjectExpression()) {
ObjectExpression objectExp = (ObjectExpression)next;
objectExp.writeForUpdateOfFields(printer, statement);
} else {
// must be FieldExpression
FieldExpression fieldExp = (FieldExpression)next;
fieldExp.writeForUpdateOf(printer, statement);
}
}
if (lockMode == ObjectBuildingQuery.LOCK_NOWAIT) {
printer.printString(printer.getSession().getPlatform().getNoWaitString());
}
} else {
super.printSQL(printer, statement);
}
}
/**
* INTERNAL:
* Returns collection of aliases of the tables to be locked.
* Only used by platforms that lock tables individually in FROM clause
* (platform.shouldPrintLockingClauseAfterWhereClause()==false)
* like SQLServer
*/
@Override
public Collection getAliasesOfTablesToBeLocked(SQLSelectStatement statement) {
int expected = statement.getTableAliases().size();
HashSet aliases = new HashSet(expected);
ExpressionBuilder clonedBuilder = statement.getBuilder();
Iterator<Expression> iterator = getLockedExpressions().iterator();
while (iterator.hasNext() && aliases.size() < expected) {
Expression next = iterator.next();
// Necessary as this was determined in query framework.
next = next.rebuildOn(clonedBuilder);
// next is either ObjectExpression or FieldExpression
if(next.isFieldExpression()) {
next = ((FieldExpression)next).getBaseExpression();
}
DatabaseTable[] expAliases = next.getTableAliases().keys();
for (int i=0; i<expAliases.length; i++) {
aliases.add(expAliases[i]);
}
}
return aliases;
}
}