Search in sources :

Example 11 with ParameterExpression

use of org.eclipse.persistence.internal.expressions.ParameterExpression in project eclipselink by eclipse-ee4j.

the class HermesParser method addArguments.

/**
 * Registers the input parameters derived from the JPQL expression with the {@link DatabaseQuery}.
 *
 * @param queryContext The {@link JPQLQueryContext} containing the information about the JPQL query
 * @param databaseQuery The EclipseLink {@link DatabaseQuery} where the input parameter types are added
 */
private void addArguments(JPQLQueryContext queryContext, DatabaseQuery databaseQuery) {
    if (queryContext.inputParameters != null) {
        for (Map.Entry<InputParameter, Expression> entry : queryContext.inputParameters.entrySet()) {
            ParameterExpression parameter = (ParameterExpression) entry.getValue();
            databaseQuery.addArgument(parameter.getField().getName(), (Class<?>) parameter.getType(), entry.getKey().isPositional() ? ParameterType.POSITIONAL : ParameterType.NAMED);
        }
    }
}
Also used : ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) Expression(org.eclipse.persistence.expressions.Expression) JPQLExpression(org.eclipse.persistence.jpa.jpql.parser.JPQLExpression) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) Map(java.util.Map) InputParameter(org.eclipse.persistence.jpa.jpql.parser.InputParameter)

Example 12 with ParameterExpression

use of org.eclipse.persistence.internal.expressions.ParameterExpression in project eclipselink by eclipse-ee4j.

the class DatasourceCall method translateQueryString.

/**
 * INTERNAL:
 * Allow the call to translate from the translation for predefined calls.
 */
public void translateQueryString(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) {
    // has a '?'
    if ((this.parameters == null) || getParameters().isEmpty()) {
        // has no parameters
        return;
    }
    if (getQueryString().indexOf(argumentMarker()) == -1) {
        return;
    }
    int lastIndex = 0;
    int parameterIndex = 0;
    String queryString = getQueryString();
    Writer writer = new CharArrayWriter(queryString.length() + 50);
    try {
        // PERF: This method is heavily optimized do not touch anything unless you know "very well" what your doing.
        // Must translate field parameters and may get new bound parameters for large data.
        List parameterFields = getParameters();
        List<Integer> parameterTypes = getParameterTypes();
        setParameters(new ArrayList(parameterFields.size()));
        while (lastIndex != -1) {
            int tokenIndex = queryString.indexOf(argumentMarker(), lastIndex);
            String token;
            if (tokenIndex == -1) {
                token = queryString.substring(lastIndex, queryString.length());
                lastIndex = -1;
            } else {
                if (this.shouldProcessTokenInQuotes) {
                    token = queryString.substring(lastIndex, tokenIndex);
                } else {
                    boolean hasPairedQuoteBeforeMark = true;
                    int quotePairIndex = tokenIndex;
                    do {
                        quotePairIndex = queryString.lastIndexOf('\'', quotePairIndex - 1);
                        if (quotePairIndex != -1 && quotePairIndex > lastIndex) {
                            hasPairedQuoteBeforeMark = !hasPairedQuoteBeforeMark;
                        } else {
                            break;
                        }
                    } while (true);
                    int endQuoteIndex = -1;
                    if (!hasPairedQuoteBeforeMark) {
                        // there is a begin quote, so search for end quote.
                        endQuoteIndex = queryString.indexOf('\'', tokenIndex + 1);
                    }
                    if (endQuoteIndex != -1) {
                        // there is a quote around the mark.
                        token = queryString.substring(lastIndex, endQuoteIndex + 1);
                        tokenIndex = -1;
                        lastIndex = endQuoteIndex + 1;
                    } else {
                        // if no quote around the mark, write the rest of sql.
                        token = queryString.substring(lastIndex, tokenIndex);
                        lastIndex = tokenIndex + 1;
                    }
                }
            }
            writer.write(token);
            if (tokenIndex != -1) {
                // Process next parameter.
                Integer parameterType = parameterTypes.get(parameterIndex);
                Object parameter = parameterFields.get(parameterIndex);
                if (parameterType == MODIFY) {
                    DatabaseField field = (DatabaseField) parameter;
                    Object value = modifyRow.get(field);
                    appendParameter(writer, value, session);
                } else if (parameterType == CUSTOM_MODIFY) {
                    DatabaseField field = (DatabaseField) parameter;
                    Object value = modifyRow.get(field);
                    if (value != null) {
                        value = session.getDatasourcePlatform().getCustomModifyValueForCall(this, value, field, false);
                        // Bug#5200826 needs use unwrapped connection.
                        if ((value instanceof BindCallCustomParameter) && ((BindCallCustomParameter) value).shouldUseUnwrappedConnection()) {
                            this.isNativeConnectionRequired = true;
                        }
                    }
                    appendParameter(writer, value, session);
                } else if (parameterType == TRANSLATION) {
                    Object value = null;
                    // Parameter expressions are used for nesting and correct mapping conversion of the value.
                    if (parameter instanceof ParameterExpression) {
                        value = ((ParameterExpression) parameter).getValue(translationRow, getQuery(), session);
                    } else {
                        DatabaseField field = (DatabaseField) parameter;
                        value = translationRow.get(field);
                        // Must check for the modify row as well for custom SQL compatibility as only one # is required.
                        if ((value == null) && (modifyRow != null)) {
                            value = modifyRow.get(field);
                        }
                    }
                    appendParameter(writer, value, session);
                } else if (parameterType == LITERAL) {
                    if (parameter instanceof DatabaseField) {
                        parameter = null;
                    }
                    appendParameter(writer, parameter, session);
                } else if (parameterType == IN) {
                    Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, false);
                    appendParameter(writer, value, session);
                } else if (parameterType == INOUT) {
                    Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session);
                    appendParameter(writer, value, session);
                } else if (parameterType == INLINE) {
                    writer.write((String) parameter);
                } else if (parameterType == OUT || parameterType == OUT_CURSOR) {
                    if (parameter instanceof DatabaseField) {
                        parameter = null;
                    }
                    appendParameter(writer, parameter, session);
                }
                lastIndex = tokenIndex + 1;
                parameterIndex++;
            }
        }
        setQueryString(writer.toString());
    } catch (IOException exception) {
        throw ValidationException.fileError(exception);
    }
}
Also used : ArrayList(java.util.ArrayList) IOException(java.io.IOException) CharArrayWriter(java.io.CharArrayWriter) ObjectRelationalDatabaseField(org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) ArrayList(java.util.ArrayList) List(java.util.List) CharArrayWriter(java.io.CharArrayWriter) Writer(java.io.Writer)

Example 13 with ParameterExpression

use of org.eclipse.persistence.internal.expressions.ParameterExpression 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();
}
Also used : SQLCall(org.eclipse.persistence.queries.SQLCall) DataExpression(org.eclipse.persistence.internal.expressions.DataExpression) ExpressionIterator(org.eclipse.persistence.internal.expressions.ExpressionIterator) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) ConstantExpression(org.eclipse.persistence.internal.expressions.ConstantExpression) QueryKeyExpression(org.eclipse.persistence.internal.expressions.QueryKeyExpression) Iterator(java.util.Iterator) ExpressionIterator(org.eclipse.persistence.internal.expressions.ExpressionIterator) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) List(java.util.List) ArrayList(java.util.ArrayList) Vector(java.util.Vector) NonSynchronizedVector(org.eclipse.persistence.internal.helper.NonSynchronizedVector) HashSet(java.util.HashSet) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder) FieldExpression(org.eclipse.persistence.internal.expressions.FieldExpression) FieldExpression(org.eclipse.persistence.internal.expressions.FieldExpression) ConstantExpression(org.eclipse.persistence.internal.expressions.ConstantExpression) QueryKeyExpression(org.eclipse.persistence.internal.expressions.QueryKeyExpression) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) ObjectExpression(org.eclipse.persistence.internal.expressions.ObjectExpression) DataExpression(org.eclipse.persistence.internal.expressions.DataExpression) Expression(org.eclipse.persistence.expressions.Expression) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) SQLSelectStatement(org.eclipse.persistence.internal.expressions.SQLSelectStatement) Collection(java.util.Collection) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) UpdateAllQuery(org.eclipse.persistence.queries.UpdateAllQuery) OptimisticLockingPolicy(org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy)

Example 14 with ParameterExpression

use of org.eclipse.persistence.internal.expressions.ParameterExpression in project eclipselink by eclipse-ee4j.

the class ForeignReferenceQueryKey method getRelationTable.

/**
 * PUBLIC:
 * Returns the relation table.
 * Currently only ManyToMany and OneToOne may have relation table.
 * The method is overridden to return null for other subclasses.
 * The returned relationTable still could be null.
 */
public DatabaseTable getRelationTable(ClassDescriptor referenceDescriptor) {
    ExpressionIterator expIterator = new ExpressionIterator() {

        @Override
        public void iterate(Expression each) {
            if (each.isTableExpression()) {
                ((Collection) this.getResult()).add(((TableExpression) each).getTable());
            } else if (each.isDataExpression()) {
                DatabaseField field = ((DataExpression) each).getField();
                if (field != null && field.hasTableName()) {
                    ((Collection) this.getResult()).add(field.getTable());
                }
            } else if (each.isParameterExpression()) {
                DatabaseField field = ((ParameterExpression) each).getField();
                if (field != null && field.hasTableName()) {
                    ((Collection) this.getResult()).add(field.getTable());
                }
            }
        }
    };
    expIterator.setResult(new HashSet());
    expIterator.iterateOn(this.joinCriteria);
    HashSet<DatabaseTable> tables = (HashSet) expIterator.getResult();
    DatabaseTable relationTable = null;
    Iterator<DatabaseTable> it = tables.iterator();
    while (it.hasNext()) {
        DatabaseTable table = it.next();
        // neither source nor reference descriptor contains table - must be relationTable
        if (!descriptor.getTables().contains(table) && !referenceDescriptor.getTables().contains(table)) {
            relationTable = table;
            break;
        }
    }
    return relationTable;
}
Also used : ExpressionIterator(org.eclipse.persistence.internal.expressions.ExpressionIterator) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) DataExpression(org.eclipse.persistence.internal.expressions.DataExpression) TableExpression(org.eclipse.persistence.internal.expressions.TableExpression) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) Collection(java.util.Collection) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) HashSet(java.util.HashSet)

Example 15 with ParameterExpression

use of org.eclipse.persistence.internal.expressions.ParameterExpression in project eclipselink by eclipse-ee4j.

the class StoredProcedureGenerator method buildProcedureString.

/**
 * INTERNAL: Given a call, this method produces the stored procedure string
 * based on the SQL string inside the call.
 */
protected String buildProcedureString(SQLCall call) {
    String stringToModify = call.getSQLString();
    String replacementToken = getSession().getPlatform().getStoredProcedureParameterPrefix();
    StringWriter stringWriter = new StringWriter();
    int startIndex = 0;
    int nextParamIndex = 0;
    int tokenIndex = stringToModify.indexOf('?');
    while (tokenIndex != -1) {
        stringWriter.write(stringToModify.substring(startIndex, tokenIndex));
        startIndex = tokenIndex + 1;
        Object parameter = call.getParameters().get(nextParamIndex);
        if (parameter instanceof DatabaseField) {
            stringWriter.write(replacementToken);
            stringWriter.write(((DatabaseField) parameter).getName());
        } else if (parameter instanceof ParameterExpression) {
            stringWriter.write(replacementToken);
            stringWriter.write(((ParameterExpression) parameter).getField().getName());
        } else {
            getSession().getPlatform().appendParameter(call, stringWriter, parameter);
        }
        tokenIndex = stringToModify.indexOf('?', startIndex);
        nextParamIndex++;
    }
    stringWriter.write(stringToModify.substring(startIndex));
    return stringWriter.toString();
}
Also used : StringWriter(java.io.StringWriter) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression)

Aggregations

ParameterExpression (org.eclipse.persistence.internal.expressions.ParameterExpression)15 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)8 Expression (org.eclipse.persistence.expressions.Expression)7 ArrayList (java.util.ArrayList)5 List (java.util.List)5 ConstantExpression (org.eclipse.persistence.internal.expressions.ConstantExpression)4 FieldExpression (org.eclipse.persistence.internal.expressions.FieldExpression)4 QueryKeyExpression (org.eclipse.persistence.internal.expressions.QueryKeyExpression)4 Collection (java.util.Collection)3 ExpressionIterator (org.eclipse.persistence.internal.expressions.ExpressionIterator)3 HashSet (java.util.HashSet)2 Map (java.util.Map)2 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)2 ObjectBuilder (org.eclipse.persistence.internal.descriptors.ObjectBuilder)2 DataExpression (org.eclipse.persistence.internal.expressions.DataExpression)2 FunctionExpression (org.eclipse.persistence.internal.expressions.FunctionExpression)2 ObjectExpression (org.eclipse.persistence.internal.expressions.ObjectExpression)2 DatabaseTable (org.eclipse.persistence.internal.helper.DatabaseTable)2 ObjectRelationalDatabaseField (org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField)2 EntityManager (jakarta.persistence.EntityManager)1