use of org.eclipse.persistence.internal.expressions.SQLSelectStatement in project eclipselink by eclipse-ee4j.
the class LOBValueWriter method buildAndExecuteCall.
protected void buildAndExecuteCall(DatabaseCall dbCall, AbstractSession session) {
DatabaseQuery query = dbCall.getQuery();
if (!query.isWriteObjectQuery()) {
// if not writequery, should not go through the locator writing..
return;
}
WriteObjectQuery writeQuery = (WriteObjectQuery) query;
writeQuery.setAccessor(accessor);
// build a select statement form the query
SQLSelectStatement selectStatement = buildSelectStatementForLocator(writeQuery, dbCall, session);
// then build a call from the statement
DatabaseCall call = buildCallFromSelectStatementForLocator(selectStatement, writeQuery, dbCall, session);
accessor.executeCall(call, call.getQuery().getTranslationRow(), session);
}
use of org.eclipse.persistence.internal.expressions.SQLSelectStatement in project eclipselink by eclipse-ee4j.
the class CascadeLockingPolicy method initUnmappedFieldsQuery.
/**
* INTERNAL:
* This method called in case there are m_unmappedQueryKeyFields.
* It creates a query that would fetch the values for this fields from the db.
*/
public void initUnmappedFieldsQuery(UnitOfWorkImpl uow) {
if (m_unmappedFieldsQuery == null) {
m_unmappedFieldsQuery = new DataReadQuery();
Expression whereClause = null;
Expression builder = new ExpressionBuilder();
Iterator<DatabaseField> itPrimaryKey = m_descriptor.getPrimaryKeyFields().iterator();
while (itPrimaryKey.hasNext()) {
DatabaseField primaryKey = itPrimaryKey.next();
Expression expression = builder.getField(primaryKey).equal(builder.getParameter(primaryKey));
whereClause = expression.and(whereClause);
m_unmappedFieldsQuery.addArgument(primaryKey.getQualifiedName());
}
SQLSelectStatement statement = new SQLSelectStatement();
Iterator<DatabaseField> itUnmappedFields = m_unmappedQueryKeyFields.values().iterator();
while (itUnmappedFields.hasNext()) {
DatabaseField field = itUnmappedFields.next();
statement.addField(field);
}
statement.setWhereClause(whereClause);
statement.normalize(uow.getParent(), m_descriptor);
m_unmappedFieldsQuery.setSQLStatement(statement);
m_unmappedFieldsQuery.setSessionName(m_descriptor.getSessionName());
}
}
use of org.eclipse.persistence.internal.expressions.SQLSelectStatement in project eclipselink by eclipse-ee4j.
the class ExpressionQueryMechanism method prepareUpdateAll.
/**
* Pre-build the SQL statement from the expressions.
*/
@Override
public void prepareUpdateAll() {
ExpressionBuilder builder = ((UpdateAllQuery) getQuery()).getExpressionBuilder();
HashMap updateClauses = ((UpdateAllQuery) getQuery()).getUpdateClauses();
boolean updateClausesHasBeenCloned = false;
// Add a statement to update the optimistic locking field if their is one.
OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
if (policy != null) {
if (policy.getWriteLockField() != null) {
Expression writeLock = builder.getField(policy.getWriteLockField());
// already targeted for update.
if (!isFieldInUpdate(writeLock, updateClauses)) {
Expression writeLockUpdateExpression = policy.getWriteLockUpdateExpression(builder, getQuery().getSession());
if (writeLockUpdateExpression != null) {
// clone it to keep user's original data intact
updateClauses = (HashMap) updateClauses.clone();
updateClausesHasBeenCloned = true;
updateClauses.put(writeLock, writeLockUpdateExpression);
}
}
}
}
if (getDescriptor().hasSerializedObjectPolicy()) {
if (!updateClausesHasBeenCloned) {
// clone it to keep user's original data intact
updateClauses = (HashMap) updateClauses.clone();
updateClausesHasBeenCloned = true;
}
Expression sopFieldExpression = builder.getField(getDescriptor().getSerializedObjectPolicy().getField());
updateClauses.put(sopFieldExpression, new ConstantExpression(null, sopFieldExpression));
}
HashMap tables_databaseFieldsToValues = new HashMap();
HashMap<DatabaseTable, List<DatabaseField>> tablesToPrimaryKeyFields = new HashMap();
Iterator it = updateClauses.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object fieldObject = entry.getKey();
DataExpression fieldExpression = null;
// QueryKeyExpression or FieldExpression of the field
Expression baseExpression = null;
String attributeName = null;
if (fieldObject instanceof String) {
attributeName = (String) fieldObject;
} else {
// it should be either QueryKeyExpression or FieldExpression
fieldExpression = (DataExpression) fieldObject;
}
DatabaseField field = null;
DatabaseMapping mapping = null;
if (attributeName != null) {
mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(attributeName);
if (mapping != null && !mapping.getFields().isEmpty()) {
field = mapping.getFields().get(0);
}
if (field == null) {
throw QueryException.updateAllQueryAddUpdateDoesNotDefineField(getDescriptor(), getQuery(), attributeName);
}
baseExpression = ((UpdateAllQuery) getQuery()).getExpressionBuilder().get(attributeName);
} else if (fieldExpression != null) {
// it should be either QueryKeyExpression or ExpressionBuilder
if (fieldExpression.getBaseExpression() instanceof ExpressionBuilder) {
field = getDescriptor().getObjectBuilder().getFieldForQueryKeyName(fieldExpression.getName());
}
if (field == null) {
DataExpression fieldExpressionClone = (DataExpression) fieldExpression.clone();
fieldExpressionClone.getBuilder().setQueryClass(getQuery().getReferenceClass());
fieldExpressionClone.getBuilder().setSession(getSession().getRootSession(null));
field = fieldExpressionClone.getField();
if (field == null) {
throw QueryException.updateAllQueryAddUpdateDoesNotDefineField(getDescriptor(), getQuery(), fieldExpression.toString());
}
}
mapping = getDescriptor().getObjectBuilder().getMappingForField(field);
baseExpression = fieldExpression;
}
Object valueObject = entry.getValue();
Vector fields;
Vector values;
Vector baseExpressions;
if (mapping != null && mapping.isOneToOneMapping()) {
fields = mapping.getFields();
int fieldsSize = fields.size();
values = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldsSize);
baseExpressions = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldsSize);
for (int i = 0; i < fieldsSize; i++) {
if (valueObject instanceof ConstantExpression) {
valueObject = ((ConstantExpression) valueObject).getValue();
}
if (valueObject == null) {
values.add(null);
} else {
DatabaseField targetField = ((OneToOneMapping) mapping).getSourceToTargetKeyFields().get(fields.get(i));
if (valueObject instanceof Expression) {
Expression exp = ((Expression) ((Expression) valueObject).clone()).getField(targetField);
if (exp.isParameterExpression()) {
((ParameterExpression) exp).setType(targetField.getType());
}
values.add(exp);
} else {
values.add(mapping.getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(valueObject, targetField, getSession()));
}
}
baseExpressions.add(new FieldExpression((DatabaseField) fields.elementAt(i), ((QueryKeyExpression) baseExpression).getBaseExpression()));
}
} else {
fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
fields.add(field);
values = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
values.add(valueObject);
baseExpressions = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
baseExpressions.add(baseExpression);
}
int fieldsSize = fields.size();
for (int i = 0; i < fieldsSize; i++) {
field = (DatabaseField) fields.elementAt(i);
DatabaseTable table = field.getTable();
if (!getDescriptor().getTables().contains(table)) {
if (attributeName != null) {
throw QueryException.updateAllQueryAddUpdateDefinesWrongField(getDescriptor(), getQuery(), attributeName, field.getQualifiedName());
} else {
throw QueryException.updateAllQueryAddUpdateDefinesWrongField(getDescriptor(), getQuery(), fieldExpression.toString(), field.getQualifiedName());
}
}
HashMap databaseFieldsToValues = (HashMap) tables_databaseFieldsToValues.get(table);
if (databaseFieldsToValues == null) {
databaseFieldsToValues = new HashMap();
tables_databaseFieldsToValues.put(table, databaseFieldsToValues);
tablesToPrimaryKeyFields.put(table, getPrimaryKeyFieldsForTable(table));
}
Object value = values.elementAt(i);
Expression valueExpression;
if (valueObject instanceof Expression) {
valueExpression = (Expression) value;
} else {
valueExpression = builder.value(value);
}
// NOTE: If baseExpression is FieldExpression, conversion is not required.
if (valueExpression.isValueExpression()) {
valueExpression.setLocalBase((Expression) baseExpressions.elementAt(i));
}
databaseFieldsToValues.put(field, valueExpression);
}
}
SQLCall selectCallForExist = null;
SQLSelectStatement selectStatementForExist = createSQLSelectStatementForModifyAll(getSelectionCriteria());
// Main Case: Descriptor is mapped to more than one table and/or the query references other tables
boolean isMainCase = selectStatementForExist.requiresAliases();
if (isMainCase) {
if (getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll()) {
prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
return;
}
}
selectCallForExist = (SQLCall) selectStatementForExist.buildCall(getSession());
// ExpressionIterator to search for valueExpressions that require select statements.
// Those are expressions that
// either reference other tables:
// Employee-based example: valueExp = builder.get("address").get("city");
// or use DataExpressions with base not ExpressionBuilder:
// Employee-base example: valueExp = builder.get("manager").get("firstName");
// Before iterating the table is set into result,
// if expression requiring select is found, then resul set to null.
ExpressionIterator expRequiresSelectIterator = new ExpressionIterator() {
@Override
public void iterate(Expression each) {
if (getResult() == null) {
return;
}
if (each instanceof DataExpression) {
DataExpression dataExpression = (DataExpression) each;
Expression baseExpression = dataExpression.getBaseExpression();
if (baseExpression != null && !(baseExpression instanceof ExpressionBuilder)) {
boolean stop = true;
if (baseExpression instanceof DataExpression) {
DataExpression baseDataExpression = (DataExpression) baseExpression;
if (baseDataExpression.getMapping() != null && baseDataExpression.getMapping().isAggregateObjectMapping()) {
stop = false;
}
}
if (stop) {
setResult(null);
return;
}
}
// Like ....CONCAT('abcd', column)....
if (baseExpression != null && (baseExpression instanceof ExpressionBuilder) && baseExpression.getSession() == null) {
((ExpressionBuilder) baseExpression).setSession(getSession());
}
DatabaseField field = dataExpression.getField();
if (field != null) {
if (!field.getTable().equals((DatabaseTable) getResult())) {
setResult(null);
return;
}
}
}
}
@Override
public boolean shouldIterateOverSubSelects() {
return true;
}
};
HashMap tables_databaseFieldsToValuesCopy = new HashMap();
it = tables_databaseFieldsToValues.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
DatabaseTable table = (DatabaseTable) entry.getKey();
HashMap databaseFieldsToValues = (HashMap) entry.getValue();
HashMap databaseFieldsToValuesCopy = new HashMap();
tables_databaseFieldsToValuesCopy.put(table, databaseFieldsToValuesCopy);
Iterator itFieldsToValues = databaseFieldsToValues.entrySet().iterator();
while (itFieldsToValues.hasNext()) {
Map.Entry entry2 = (Map.Entry) itFieldsToValues.next();
DatabaseField field = (DatabaseField) entry2.getKey();
Expression value = (Expression) entry2.getValue();
// initialize result with the table
expRequiresSelectIterator.setResult(table);
// To find fields have to have session and ref class
Expression valueClone = (Expression) value.clone();
valueClone.getBuilder().setSession(getSession());
valueClone.getBuilder().setQueryClass(getQuery().getReferenceClass());
expRequiresSelectIterator.iterateOn(valueClone);
if (expRequiresSelectIterator.getResult() == null) {
// The corresponding SelectionStatement should be assigned to value
if (getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll()) {
prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
return;
}
SQLSelectStatement selStatement = createSQLSelectStatementForAssignedExpressionForUpdateAll(value);
databaseFieldsToValuesCopy.put(field, selStatement);
} else {
databaseFieldsToValuesCopy.put(field, valueClone);
}
}
}
HashMap tables_databaseFieldsToValuesOriginal = tables_databaseFieldsToValues;
tables_databaseFieldsToValues = tables_databaseFieldsToValuesCopy;
if (tables_databaseFieldsToValues.size() == 1) {
Map.Entry entry = (Map.Entry) tables_databaseFieldsToValues.entrySet().iterator().next();
DatabaseTable table = (DatabaseTable) entry.getKey();
HashMap databaseFieldsToValues = (HashMap) entry.getValue();
Collection<DatabaseField> primaryKeyFields = tablesToPrimaryKeyFields.values().iterator().next();
setSQLStatement(buildUpdateAllStatement(table, databaseFieldsToValues, selectCallForExist, selectStatementForExist, primaryKeyFields));
} else {
// To figure out the order of statements we need to find dependencies
// between updating of tables.
// Here's an example:
// All objects with nameA = "Clob" should be changed so that nameA = "Alex" and nameB = "Bob";
// nameA is mapped to A.name and nameB mapped to B.name:
// UPDATE B SET B.name = "Bob" WHERE A.name = "Clob" and A.id = B.id;
// UPDATE A SET A.name = "Alex" WHERE A.name = "Clob" and A.id = B.id;
// The order can't be altered - or there will be no updating of B.
// To formalize that: for each table we'll gather two Collections:
// leftFields - all the table's fields to receive a new value;
// rightFields - all the fields either in assigned or selecton expression.
// A_leftFields = {A.name}; A_rightFields = {A.name}.
// B_leftFields = {B.name}; B_rightFields = {A.name}.
// There are several comparison outcomes:
// 1. A_leftFields doesn't intersect B_rightFields and
// B_leftFields doesn't intersect A_rightFields
// There is no dependency - doesn't matter which update goes first;
// 2. A_leftFields intersects B_rightFields and
// B_leftFields doesn't intersect A_rightFields
// B should be updated before A (the case in the example).
// 3. A_leftFields intersects B_rightFields and
// B_leftFields intersects A_rightFields
// Ordering conflict that can't be resolved without using transitionary storage.
//
// This ExpressionIterator will be used for collecting fields from
// selection criteria and assigned expressions.
ExpressionIterator expIterator = new ExpressionIterator() {
@Override
public void iterate(Expression each) {
if (each instanceof DataExpression) {
DataExpression dataExpression = (DataExpression) each;
DatabaseField field = dataExpression.getField();
if (field != null) {
((Collection) getResult()).add(field);
}
}
}
@Override
public boolean shouldIterateOverSubSelects() {
return true;
}
};
// This will hold collection of fields from selection criteria expression.
HashSet selectCallForExistFields = new HashSet();
if (selectCallForExist != null) {
expIterator.setResult(selectCallForExistFields);
expIterator.iterateOn(selectStatementForExist.getWhereClause());
}
// Left of the assignment operator that is - the fields acquiring new values
HashMap tablesToLeftFields = new HashMap();
// The fields right of the assignment operator AND the fields from whereClause
HashMap tablesToRightFields = new HashMap();
// before and after vectors work together: n-th member of beforeTable should
// be updated before than n-th member of afterTable
Vector beforeTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
Vector afterTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
// Both keys and values are tables.
// An entry indicates a timing conflict between the key and the value:
// both key should be updated before value and value before key.
HashMap simpleConflicts = new HashMap();
it = tables_databaseFieldsToValues.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
// for each table to be updated
DatabaseTable table = (DatabaseTable) entry.getKey();
// here's a Map of left hand fields to right hand expressions
HashMap databaseFieldsToValues = (HashMap) entry.getValue();
// This will contain all the left hand fields
HashSet leftFields = new HashSet(databaseFieldsToValues.size());
// This will contain all the left hand fields plus fields form selection criteria
HashSet rightFields = (HashSet) selectCallForExistFields.clone();
expIterator.setResult(rightFields);
Iterator itDatabaseFieldsToValues = databaseFieldsToValues.entrySet().iterator();
while (itDatabaseFieldsToValues.hasNext()) {
// for each left hand - right hand expression pair
Map.Entry databaseFieldValueEntry = (Map.Entry) itDatabaseFieldsToValues.next();
// here's the left hand database field
DatabaseField field = (DatabaseField) databaseFieldValueEntry.getKey();
leftFields.add(field);
// here's the right hand expression
Object value = databaseFieldValueEntry.getValue();
if (value instanceof Expression) {
Expression valueExpression = (Expression) value;
// use iterator to extract all the fields
expIterator.iterateOn(valueExpression);
} else {
// It should be SQLSelectStatement with a single field
SQLSelectStatement selStatement = (SQLSelectStatement) value;
// first one is the normalized value to be assigned
expIterator.iterateOn((Expression) selStatement.getFields().get(0));
// whereClause - generated during normalization
expIterator.iterateOn(selStatement.getWhereClause());
}
}
// now let's compare the table with the already processed tables
Iterator itProcessedTables = tablesToLeftFields.keySet().iterator();
while (itProcessedTables.hasNext()) {
DatabaseTable processedTable = (DatabaseTable) itProcessedTables.next();
HashSet processedTableLeftFields = (HashSet) tablesToLeftFields.get(processedTable);
HashSet processedTableRightFields = (HashSet) tablesToRightFields.get(processedTable);
boolean tableBeforeProcessedTable = false;
Iterator itProcessedTableLeftField = processedTableLeftFields.iterator();
while (itProcessedTableLeftField.hasNext()) {
if (rightFields.contains(itProcessedTableLeftField.next())) {
tableBeforeProcessedTable = true;
break;
}
}
boolean processedTableBeforeTable = false;
Iterator itLeftField = leftFields.iterator();
while (itLeftField.hasNext()) {
if (processedTableRightFields.contains(itLeftField.next())) {
processedTableBeforeTable = true;
break;
}
}
if (tableBeforeProcessedTable && !processedTableBeforeTable) {
// table should be updated before processedTable
beforeTables.add(table);
afterTables.add(processedTable);
} else if (!tableBeforeProcessedTable && processedTableBeforeTable) {
// processedTable should be updated before table
beforeTables.add(processedTable);
afterTables.add(table);
} else if (tableBeforeProcessedTable && processedTableBeforeTable) {
// there is an order conflict between table and processTable
simpleConflicts.put(processedTable, table);
}
}
tablesToLeftFields.put(table, leftFields);
tablesToRightFields.put(table, rightFields);
}
if (!simpleConflicts.isEmpty()) {
prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValuesOriginal, tablesToPrimaryKeyFields);
return;
}
// This will contain tables in update order
Vector orderedTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(tables_databaseFieldsToValues.size());
// first process the tables found in beforeTables / afterTables
while (!beforeTables.isEmpty()) {
// Find firstTable - the one that appears in beforeTables, but not afterTables.
// That means there is no requirement to update it after any other table and we
// can put it first in update order. There could be several such tables -
// it doesn't matter which one will be picked.
DatabaseTable firstTable = null;
for (int i = 0; i < beforeTables.size(); i++) {
DatabaseTable beforeTable = (DatabaseTable) beforeTables.elementAt(i);
if (!afterTables.contains(beforeTable)) {
firstTable = beforeTable;
break;
}
}
if (firstTable == null) {
// There is no firstTable - it's an order conflict between three or more tables
prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValuesOriginal, tablesToPrimaryKeyFields);
return;
} else {
// Also remove the corresponding entries from afterTable.
for (int i = beforeTables.size() - 1; i >= 0; i--) {
if (beforeTables.elementAt(i).equals(firstTable)) {
beforeTables.remove(i);
afterTables.remove(i);
}
}
// Add firstTable to orderedTables
orderedTables.addElement(firstTable);
}
}
// now all the remaining ones - there are no dependencies between them
// so the order is arbitrary.
Iterator itTables = tables_databaseFieldsToValues.keySet().iterator();
while (itTables.hasNext()) {
DatabaseTable table = (DatabaseTable) itTables.next();
if (!orderedTables.contains(table)) {
orderedTables.add(table);
}
}
// finally create statements
for (int i = 0; i < orderedTables.size(); i++) {
DatabaseTable table = (DatabaseTable) orderedTables.elementAt(i);
HashMap databaseFieldsToValues = (HashMap) tables_databaseFieldsToValues.get(table);
Collection<DatabaseField> primaryKeyFields = tablesToPrimaryKeyFields.get(table);
getSQLStatements().addElement(buildUpdateAllStatement(table, databaseFieldsToValues, selectCallForExist, selectStatementForExist, primaryKeyFields));
}
}
((UpdateAllQuery) getQuery()).setIsPreparedUsingTempStorage(false);
super.prepareUpdateAll();
}
use of org.eclipse.persistence.internal.expressions.SQLSelectStatement in project eclipselink by eclipse-ee4j.
the class ExpressionQueryMechanism method prepareReportQuerySelectAllRows.
/**
* Pre-build the SQL statement from the expression.
*/
@Override
public void prepareReportQuerySelectAllRows() {
SQLSelectStatement statement = buildReportQuerySelectStatement(false);
setSQLStatement(statement);
setCallFromStatement();
// The statement is no longer require so can be released.
setSQLStatement(null);
getCall().returnManyRows();
prepareCall();
}
use of org.eclipse.persistence.internal.expressions.SQLSelectStatement in project eclipselink by eclipse-ee4j.
the class ExpressionQueryMechanism method buildConcreteSelectStatement.
/**
* Return the appropriate select statement containing the fields in the table.
* This is used as a second read to a concrete class with subclasses in an abstract-multiple table read.
*/
protected SQLSelectStatement buildConcreteSelectStatement() {
// 2612538 - the default size of Map (32) is appropriate
Map clonedExpressions = new IdentityHashMap();
SQLSelectStatement selectStatement = buildBaseSelectStatement(false, clonedExpressions);
ClassDescriptor descriptor = getDescriptor();
InheritancePolicy policy = descriptor.getInheritancePolicy();
// so if a root or branch (!shouldReadSubclasses means leaf), then it must be appended.
if (policy.shouldReadSubclasses()) {
Expression indicatorExpression = null;
// If the descriptor is a single table branch, then select the whole branch in a single query.
if (this.query.isReadAllQuery() && policy.hasChildren() && !policy.hasMultipleTableChild()) {
indicatorExpression = policy.getWithAllSubclassesExpression();
} else {
indicatorExpression = policy.getOnlyInstancesExpression();
}
if ((indicatorExpression != null) && (selectStatement.getWhereClause() != null)) {
selectStatement.setWhereClause(selectStatement.getWhereClause().and(indicatorExpression));
} else if (indicatorExpression != null) {
selectStatement.setWhereClause((Expression) indicatorExpression.clone());
}
}
selectStatement.setFields(getSelectionFields(selectStatement, false));
selectStatement.normalize(getSession(), descriptor, clonedExpressions);
// Allow for joining indexes to be computed to ensure distinct rows.
if (((ObjectLevelReadQuery) this.query).hasJoining()) {
((ObjectLevelReadQuery) this.query).getJoinedAttributeManager().computeJoiningMappingIndexes(false, getSession(), 0);
}
return selectStatement;
}
Aggregations