use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class OneToManyMapping method initializeRemoveTargetQuery.
/**
* INTERNAL:
* Initialize removeTargetQuery.
*/
protected void initializeRemoveTargetQuery(AbstractSession session) {
if (!removeTargetQuery.hasSessionName()) {
removeTargetQuery.setSessionName(session.getName());
}
if (hasCustomRemoveTargetQuery) {
return;
}
// All targetForeignKeys should have the same table
DatabaseTable table = targetForeignKeyFields.get(0).getTable();
// Build where clause expression.
Expression whereClause = null;
Expression builder = new ExpressionBuilder();
int size = targetPrimaryKeyFields.size();
for (int index = 0; index < size; index++) {
DatabaseField targetPrimaryKey = targetPrimaryKeyFields.get(index);
Expression expression = builder.getField(targetPrimaryKey).equal(builder.getParameter(targetPrimaryKey));
whereClause = expression.and(whereClause);
}
AbstractRecord modifyRow = new DatabaseRecord();
if (shouldRemoveTargetQueryModifyTargetForeignKey()) {
size = targetForeignKeyFields.size();
for (int index = 0; index < size; index++) {
DatabaseField targetForeignKey = targetForeignKeyFields.get(index);
modifyRow.put(targetForeignKey, null);
Expression expression = builder.getField(targetForeignKey).equal(builder.getParameter(targetForeignKey));
whereClause = expression.and(whereClause);
}
}
if (listOrderField != null) {
modifyRow.add(listOrderField, null);
}
SQLUpdateStatement statement = new SQLUpdateStatement();
statement.setTable(table);
statement.setWhereClause(whereClause);
statement.setModifyRow(modifyRow);
removeTargetQuery.setSQLStatement(statement);
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class ForeignReferenceMapping method trimRowForJoin.
/**
* INTERNAL:
* Return a sub-partition of the row starting at the index.
*/
public AbstractRecord trimRowForJoin(AbstractRecord row, Object value, AbstractSession executionSession) {
// CR #... the field for many objects may be in the row,
// so build the subpartion of the row through the computed values in the query,
// this also helps the field indexing match.
int fieldStartIndex;
if (value instanceof Integer) {
fieldStartIndex = (Integer) value;
} else {
// must be Map of classes to Integers
Map map = (Map) value;
Class<?> cls;
if (getDescriptor().hasInheritance() && getDescriptor().getInheritancePolicy().shouldReadSubclasses()) {
cls = getDescriptor().getInheritancePolicy().classFromRow(row, executionSession);
} else {
cls = getDescriptor().getJavaClass();
}
fieldStartIndex = (Integer) map.get(cls);
}
Vector<DatabaseField> trimedFields = new NonSynchronizedSubVector<>(row.getFields(), fieldStartIndex, row.size());
Vector trimedValues = new NonSynchronizedSubVector(row.getValues(), fieldStartIndex, row.size());
return new DatabaseRecord(trimedFields, trimedValues);
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class ForeignReferenceMapping method extractResultFromBatchQuery.
/**
* INTERNAL:
* Extract the value from the batch optimized query, this should be supported by most query types.
*/
public Object extractResultFromBatchQuery(ReadQuery batchQuery, CacheKey parentCacheKey, AbstractRecord sourceRow, AbstractSession session, ObjectLevelReadQuery originalQuery) throws QueryException {
Map<Object, Object> batchedObjects;
Object result;
Object sourceKey = extractBatchKeyFromRow(sourceRow, session);
if (sourceKey == null) {
// If the foreign key was null, then just return null.
return null;
}
Object cachedObject = checkCacheForBatchKey(sourceRow, sourceKey, null, batchQuery, originalQuery, session);
if (cachedObject != null) {
// If the object is already in the cache, then just return it.
return cachedObject;
}
// Ensure the query is only executed once.
synchronized (batchQuery) {
// Check if query was already executed.
batchedObjects = batchQuery.getBatchObjects();
BatchFetchPolicy originalPolicy = originalQuery.getBatchFetchPolicy();
if (batchedObjects == null) {
batchedObjects = new Hashtable<>();
batchQuery.setBatchObjects(batchedObjects);
} else {
result = batchedObjects.get(sourceKey);
if (result == Helper.NULL_VALUE) {
return null;
// If IN may not have that batch yet, or it may have been null.
} else if ((result != null) || (!originalPolicy.isIN())) {
return result;
}
}
// In case of IN the batch including this row may not have been executed yet.
AbstractRecord translationRow = originalQuery.getTranslationRow();
if (translationRow == null) {
translationRow = new DatabaseRecord();
}
// Execute query and index resulting object sets by key.
if (originalPolicy.isIN()) {
// Need to extract all foreign key values from all parent rows for IN parameter.
List<AbstractRecord> parentRows = originalPolicy.getDataResults(this);
// Execute queries by batch if too many rows.
int rowsSize = parentRows.size();
int size = Math.min(rowsSize, originalPolicy.getSize());
if (size == 0) {
return null;
}
int startIndex = 0;
if (size != rowsSize) {
// If only fetching a page, need to make sure the row we want is in the page.
startIndex = parentRows.indexOf(sourceRow);
}
if (startIndex == -1) {
return null;
}
List foreignKeyValues = new ArrayList(size);
Set foreignKeys = new HashSet(size);
int index = 0;
int offset = startIndex;
for (int count = 0; count < size; count++) {
if (index >= rowsSize) {
// Processed all rows, done.
break;
} else if ((offset + index) >= rowsSize) {
// If passed the end, go back to start.
offset = index * -1;
}
AbstractRecord row = parentRows.get(offset + index);
// result of duplicate filtering being true for constructing the ComplexQueryResult
if (row != null) {
Object foreignKey = extractBatchKeyFromRow(row, session);
if (foreignKey == null) {
// Ignore null foreign keys.
count--;
} else {
cachedObject = checkCacheForBatchKey(row, foreignKey, batchedObjects, batchQuery, originalQuery, session);
if (cachedObject != null) {
// Avoid fetching things a cache hit occurs for.
count--;
} else {
// Ensure the same id is not selected twice.
if (foreignKeys.contains(foreignKey)) {
count--;
} else {
Object[] key = ((CacheId) foreignKey).getPrimaryKey();
Object foreignKeyValue = key[0];
// Support composite keys using nested IN.
if (key.length > 1) {
foreignKeyValue = Arrays.asList(key);
}
foreignKeyValues.add(foreignKeyValue);
foreignKeys.add(foreignKey);
}
}
}
}
index++;
}
// Need to compute remaining rows, this is tricky because a page in the middle could have been processed.
List<AbstractRecord> remainingParentRows;
if (startIndex == 0) {
// Tail
remainingParentRows = new ArrayList<>(parentRows.subList(index, rowsSize));
} else if (startIndex == offset) {
// Head and tail.
remainingParentRows = new ArrayList<>(parentRows.subList(0, startIndex));
remainingParentRows.addAll(parentRows.subList(startIndex + index, rowsSize));
} else {
// Middle
remainingParentRows = new ArrayList<>(parentRows.subList(offset + index, startIndex));
}
originalPolicy.setDataResults(this, remainingParentRows);
translationRow = translationRow.clone();
translationRow.put(QUERY_BATCH_PARAMETER, foreignKeyValues);
// Register each id as null, in case it has no relationship.
for (Object foreignKey : foreignKeys) {
batchedObjects.put(foreignKey, Helper.NULL_VALUE);
}
} else if (batchQuery.isReadAllQuery() && ((ReadAllQuery) batchQuery).getBatchFetchPolicy().isIN()) {
throw QueryException.originalQueryMustUseBatchIN(this, originalQuery);
}
executeBatchQuery(batchQuery, parentCacheKey, batchedObjects, session, translationRow);
batchQuery.setSession(null);
}
result = batchedObjects.get(sourceKey);
if (result == Helper.NULL_VALUE) {
return null;
} else {
return result;
}
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class UnidirectionalOneToManyMapping method buildKeyRowForTargetUpdate.
/**
* INTERNAL:
* Build a row containing the keys for use in the query that updates the row for the
* target object during an insert or update
*/
@Override
protected AbstractRecord buildKeyRowForTargetUpdate(ObjectLevelModifyQuery query) {
AbstractRecord keyRow = new DatabaseRecord();
// Extract primary key and value from the source.
int size = sourceKeyFields.size();
for (int index = 0; index < size; index++) {
DatabaseField sourceKey = sourceKeyFields.get(index);
DatabaseField targetForeignKey = targetForeignKeyFields.get(index);
Object sourceKeyValue = query.getTranslationRow().get(sourceKey);
keyRow.put(targetForeignKey, sourceKeyValue);
}
return keyRow;
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class RelationTableMechanism method initializeInsertQuery.
/**
* INTERNAL:
* Initialize insert query. This query is used to insert the collection of objects into the
* relation table.
*/
protected void initializeInsertQuery(AbstractSession session, ForeignReferenceMapping mapping) {
if (!getInsertQuery().hasSessionName()) {
getInsertQuery().setSessionName(session.getName());
}
if (getInsertQuery().getPartitioningPolicy() == null) {
getInsertQuery().setPartitioningPolicy(mapping.getPartitioningPolicy());
}
getInsertQuery().setName(mapping.getAttributeName());
if (hasCustomInsertQuery()) {
return;
}
SQLInsertStatement statement = new SQLInsertStatement();
statement.setTable(getRelationTable());
AbstractRecord joinRow = new DatabaseRecord();
for (DatabaseField field : getTargetRelationKeyFields()) {
joinRow.put(field, null);
}
for (DatabaseField field : getSourceRelationKeyFields()) {
joinRow.put(field, null);
}
if (mapping.isCollectionMapping()) {
CollectionMapping collectionMapping = (CollectionMapping) mapping;
if (collectionMapping.getListOrderField() != null) {
joinRow.put(collectionMapping.getListOrderField(), null);
}
collectionMapping.getContainerPolicy().addFieldsForMapKey(joinRow);
}
statement.setModifyRow(joinRow);
getInsertQuery().setSQLStatement(statement);
getInsertQuery().setModifyRow(joinRow);
}
Aggregations