org.eclipse.persistence.internal.expressions.SQLUpdateAllStatement 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, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022 IBM Corporation. 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 org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.SQLCall;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
/**
* @author Guy Pelletier
* @since TOPLink/Java 1.0
*/
public class SQLUpdateAllStatement extends SQLModifyStatement {
protected Map m_updateClauses;
protected Map databaseFieldsToTableAliases;
protected SQLCall selectCallForExist;
protected String tableAliasInSelectCallForExist;
protected Collection primaryKeyFields;
protected boolean shouldExtractWhereClauseFromSelectCallForExist;
public SQLUpdateAllStatement() {
}
public void setSelectCallForExist(SQLCall selectCallForExist) {
this.selectCallForExist = selectCallForExist;
}
public SQLCall getSelectCallForExist() {
return selectCallForExist;
}
public void setTableAliasInSelectCallForExist(String tableAliasInSelectCallForExist) {
this.tableAliasInSelectCallForExist = tableAliasInSelectCallForExist;
}
public String getTableAliasInSelectCallForExist() {
return tableAliasInSelectCallForExist;
}
public void setPrimaryKeyFieldsForAutoJoin(Collection primaryKeyFields) {
this.primaryKeyFields = primaryKeyFields;
}
public Collection getPrimaryKeyFieldsForAutoJoin() {
return primaryKeyFields;
}
public void setUpdateClauses(Map updateClauses) {
m_updateClauses = updateClauses;
}
public Map getUpdateClauses() {
return m_updateClauses;
}
public void setDatabaseFieldsToTableAliases(Map databaseFieldsToTableAliases) {
this.databaseFieldsToTableAliases = databaseFieldsToTableAliases;
}
public Map getDatabaseFieldsToTableAliases() {
return databaseFieldsToTableAliases;
}
public void setShouldExtractWhereClauseFromSelectCallForExist(boolean shouldExtractWhereClauseFromSelectCallForExist) {
this.shouldExtractWhereClauseFromSelectCallForExist = shouldExtractWhereClauseFromSelectCallForExist;
}
public boolean shouldExtractWhereClauseFromSelectCallForExist() {
return shouldExtractWhereClauseFromSelectCallForExist;
}
/**
* Append the string containing the SQL insert string for the given table.
*/
@Override
public DatabaseCall buildCall(AbstractSession session) {
SQLCall call = buildSimple(session);
if(selectCallForExist == null) {
return call;
}
Writer writer = new CharArrayWriter(100);
try {
writer.write(call.getSQLString());
if(selectCallForExist != null) {
if(shouldExtractWhereClauseFromSelectCallForExist) {
// Should get here only in case selectCallForExist doesn't have aliases and
// targets the same table as the statement.
// Instead of making selectCallForExist part of " WHERE EXIST("
// just extract its where clause.
// Example: selectCallForExist.sqlString:
// "SELECT PROJ_ID FROM PROJECT WHERE (LEADER_ID IS NULL)
writeWhere(writer, selectCallForExist, call);
// The result is:
// "WHERE (LEADER_ID IS NULL)"
} else {
writer.write(" WHERE EXISTS(");
// EXIST Example: selectCall.sqlString:
// "SELECT t0.EMP_ID FROM EMPLOYEE t0, SALARY t1 WHERE (((t0.F_NAME LIKE 'a') AND (t1.SALARY = 0)) AND (t1.EMP_ID = t0.EMP_ID))"
writeSelect(writer, selectCallForExist, tableAliasInSelectCallForExist, call, session.getPlatform());
// closing bracket for EXISTS
writer.write(")");
}
// Bug 301888 - DB2: UpdateAll/DeleteAll using WHERE EXIST fail.
// If selectCallForExist has been explicitly set to not use binding then call should be set the same way.
if(selectCallForExist.isUsesBindingSet() && !selectCallForExist.usesBinding(session)) {
call.setUsesBinding(false);
}
}
call.setSQLString(writer.toString());
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
return call;
}
protected SQLCall buildSimple(AbstractSession session) {
SQLCall call = new SQLCall();
call.returnNothing();
Writer writer = new CharArrayWriter(100);
ExpressionSQLPrinter printer = new ExpressionSQLPrinter(session, getTranslationRow(), call, false, getBuilder());
printer.setWriter(writer);
try {
// UPDATE //
writer.write("UPDATE ");
// HINT STRING //
if (getHintString() != null) {
writer.write(getHintString());
writer.write(" ");
}
writer.write(getTable().getQualifiedNameDelimited(session.getPlatform()));
// SET CLAUSE //
writer.write(" SET ");
Iterator i = m_updateClauses.keySet().iterator();
boolean commaNeeded = false;
while (i.hasNext()) {
if (commaNeeded) {
writer.write(", ");
}
DatabaseField field = i.next();
Object value = m_updateClauses.get(field);
writer.write(field.getNameDelimited(session.getPlatform()));
writer.write(" = ");
if(value instanceof Expression expression) {
printer.printExpression(expression);
} else {
// must be SQLCall
SQLCall selCall = (SQLCall)value;
String tableAlias = getDatabaseFieldsToTableAliases().get(field);
// should be SQLCall select
writer.write("(");
writeSelect(writer, selCall, tableAlias, call, session.getPlatform());
writer.write(")");
}
commaNeeded = true;
}
// WHERE CLAUSE //
if (getWhereClause() != null) {
writer.write(" WHERE ");
printer.printExpression(getWhereClause());
}
call.setSQLString(writer.toString());
return call;
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}
protected void writeSelect(Writer writer, SQLCall selectCall, String tableAliasInSelectCall, SQLCall call, DatasourcePlatform platform) throws IOException {
String str = selectCall.getSQLString();
writer.write(str);
boolean hasWhereClause = str.toUpperCase().contains(" WHERE ");
// Auto join
// Example: AND t0.EMP_ID = EMP_ID
Iterator it = getPrimaryKeyFieldsForAutoJoin().iterator();
while(it.hasNext()) {
if(!hasWhereClause) {
// there is no where clause - should print WHERE
writer.write(" WHERE ");
hasWhereClause = true;
} else {
writer.write(" AND ");
}
String fieldName = it.next().getNameDelimited(platform);
if(tableAliasInSelectCall != null) {
writer.write(tableAliasInSelectCall);
writer.write('.');
}
writer.write(fieldName);
writer.write(" = ");
writer.write(table.getQualifiedNameDelimited(platform));
writer.write('.');
writer.write(fieldName);
}
call.getParameters().addAll(selectCall.getParameters());
call.getParameterTypes().addAll(selectCall.getParameterTypes());
call.getParameterBindings().addAll(selectCall.getParameterBindings());
}
protected boolean writeWhere(Writer writer, SQLCall selectCall, SQLCall call) throws IOException {
String selectStr = selectCallForExist.getSQLString();
int index = selectStr.toUpperCase().indexOf(" WHERE ");
if(index < 0) {
// no where clause - nothing to do
return false;
}
// print the where clause
String str = selectStr.substring(index);
writer.write(str);
// add parameters
call.getParameters().addAll(selectCall.getParameters());
call.getParameterTypes().addAll(selectCall.getParameterTypes());
call.getParameterBindings().addAll(selectCall.getParameterBindings());
return true;
}
}