Search in sources :

Example 16 with DatabaseRecord

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);
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) FieldExpression(org.eclipse.persistence.internal.expressions.FieldExpression) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) Expression(org.eclipse.persistence.expressions.Expression) SQLUpdateStatement(org.eclipse.persistence.internal.expressions.SQLUpdateStatement) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder)

Example 17 with DatabaseRecord

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);
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) NonSynchronizedSubVector(org.eclipse.persistence.internal.helper.NonSynchronizedSubVector) Map(java.util.Map) HashMap(java.util.HashMap) Vector(java.util.Vector) NonSynchronizedVector(org.eclipse.persistence.internal.helper.NonSynchronizedVector) NonSynchronizedSubVector(org.eclipse.persistence.internal.helper.NonSynchronizedSubVector)

Example 18 with DatabaseRecord

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;
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) UnitOfWorkChangeSet(org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) ArrayList(java.util.ArrayList) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) BatchFetchPolicy(org.eclipse.persistence.queries.BatchFetchPolicy) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 19 with DatabaseRecord

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;
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord)

Example 20 with DatabaseRecord

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);
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) SQLInsertStatement(org.eclipse.persistence.internal.expressions.SQLInsertStatement)

Aggregations

DatabaseRecord (org.eclipse.persistence.sessions.DatabaseRecord)110 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)44 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)43 Vector (java.util.Vector)31 ArrayList (java.util.ArrayList)17 NonSynchronizedVector (org.eclipse.persistence.internal.helper.NonSynchronizedVector)17 BigDecimal (java.math.BigDecimal)14 List (java.util.List)14 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)14 DatabaseSession (org.eclipse.persistence.sessions.DatabaseSession)14 Test (org.junit.Test)14 Expression (org.eclipse.persistence.expressions.Expression)12 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)12 HashMap (java.util.HashMap)11 Map (java.util.Map)10 EclipseLinkException (org.eclipse.persistence.exceptions.EclipseLinkException)7 ExpressionBuilder (org.eclipse.persistence.expressions.ExpressionBuilder)7 RelationalDescriptor (org.eclipse.persistence.descriptors.RelationalDescriptor)6 DescriptorException (org.eclipse.persistence.exceptions.DescriptorException)6 SQLUpdateStatement (org.eclipse.persistence.internal.expressions.SQLUpdateStatement)6