Search in sources :

Example 1 with CollectionUpdateModificationQuerySpecification

use of com.blazebit.persistence.impl.query.CollectionUpdateModificationQuerySpecification in project blaze-persistence by Blazebit.

the class AbstractUpdateCollectionCriteriaBuilder method getQuerySpecification.

private <R> QuerySpecification getQuerySpecification(Query baseQuery, Query exampleQuery, String[] returningColumns, ReturningObjectBuilder<R> objectBuilder, Map<DbmsModificationState, String> includedModificationStates) {
    Set<String> parameterListNames = parameterManager.getParameterListNames(baseQuery);
    boolean isEmbedded = this instanceof ReturningBuilder;
    boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
    List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;
    ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
    String sql = extendedQuerySupport.getSql(em, baseQuery);
    String ownerAlias = extendedQuerySupport.getSqlAlias(em, baseQuery, entityAlias);
    String targetAlias = extendedQuerySupport.getSqlAlias(em, baseQuery, JoinManager.COLLECTION_DML_BASE_QUERY_ALIAS);
    JoinTable joinTable = collectionAttribute.getJoinTable();
    int joinTableIndex = SqlUtils.indexOfTableName(sql, joinTable.getTableName());
    String collectionAlias = SqlUtils.extractAlias(sql, joinTableIndex + joinTable.getTableName().length());
    String tableToUpdate = joinTable.getTableName();
    String tablePrefix;
    if (mainQuery.dbmsDialect.getUpdateJoinStyle() == UpdateJoinStyle.FROM_ALIAS) {
        tablePrefix = collectionAlias;
    } else if (mainQuery.dbmsDialect.getUpdateJoinStyle() == UpdateJoinStyle.FROM) {
        tablePrefix = null;
    } else {
        tablePrefix = tableToUpdate;
    }
    List<String> setColumns = getSetColumns();
    // Prepare a Map<EntityAlias.idColumnName, CollectionAlias.idColumnName>
    // This is used to replace references to id columns properly in the final sql query
    Map<String, String> columnExpressionRemappings = new HashMap<>();
    List<String> joinTableIdColumns = new ArrayList<>();
    String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
    String discriminatorPredicate = "";
    if (discriminatorColumnCheck != null) {
        discriminatorPredicate = ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1] + " and";
        columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
    }
    if (joinTable.getKeyColumnMappings() != null) {
        for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
            joinTableIdColumns.add(entry.getKey());
            String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + collectionAlias + "." + entry.getValue() + ")";
            if (tablePrefix == null) {
                columnExpressionRemappings.put(sourceExpression, collectionAlias + "." + entry.getValue());
            } else {
                columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
            }
        }
    }
    for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
        joinTableIdColumns.add(entry.getKey());
        String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + ownerAlias + "." + entry.getValue() + ")";
        if (tablePrefix == null) {
            columnExpressionRemappings.put(sourceExpression, ownerAlias + "." + entry.getValue());
        } else {
            columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
        }
    }
    for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
        String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + targetAlias + "." + entry.getValue() + ")";
        if (tablePrefix == null) {
            columnExpressionRemappings.put(sourceExpression, targetAlias + "." + entry.getValue());
        } else {
            columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
        }
    }
    // If the id attribute is an embedded type, there is the possibility that row value expressions are used which we need to handle as well
    Set<SingularAttribute<?, ?>> idAttributes = JpaMetamodelUtils.getIdAttributes(entityType);
    if (idAttributes.size() == 1 && idAttributes.iterator().next().getType() instanceof ManagedType<?>) {
        StringBuilder leftSb = new StringBuilder();
        StringBuilder rightSb = new StringBuilder();
        leftSb.append(CollectionDmlSupportFunction.FUNCTION_NAME).append("((");
        rightSb.append("(");
        for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
            leftSb.append(ownerAlias).append('.').append(entry.getValue()).append(", ");
            if (tablePrefix == null) {
                rightSb.append(ownerAlias).append('.').append(entry.getValue()).append(',');
            } else {
                rightSb.append(tablePrefix).append('.').append(entry.getKey()).append(',');
            }
        }
        leftSb.setLength(leftSb.length() - 2);
        leftSb.append("))");
        rightSb.setCharAt(rightSb.length() - 1, ')');
        columnExpressionRemappings.put(leftSb.toString(), rightSb.toString());
    }
    Map<String, String> aliasMapping = new TreeMap<>();
    if (mainQuery.dbmsDialect.getPhysicalRowId() != null) {
        joinTableIdColumns.clear();
        joinTableIdColumns.add(mainQuery.dbmsDialect.getPhysicalRowId());
    }
    for (String idColumn : joinTableIdColumns) {
        aliasMapping.put(collectionAlias + "." + idColumn, "tmp.c" + aliasMapping.size());
    }
    SqlUtils.buildAliasMappingForTopLevelSelects(extendedQuerySupport.getSql(em, baseQuery), "tmp", aliasMapping);
    return new CollectionUpdateModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled(), tableToUpdate, collectionAlias, joinTableIdColumns.toArray(new String[0]), setColumns, getForeignKeyParticipatingQueries(), aliasMapping, getUpdateExampleQuery(), columnExpressionRemappings);
}
Also used : ReturningBuilder(com.blazebit.persistence.ReturningBuilder) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) CollectionUpdateModificationQuerySpecification(com.blazebit.persistence.impl.query.CollectionUpdateModificationQuerySpecification) SingularAttribute(javax.persistence.metamodel.SingularAttribute) ExtendedQuerySupport(com.blazebit.persistence.spi.ExtendedQuerySupport) CTENode(com.blazebit.persistence.impl.query.CTENode) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) JoinTable(com.blazebit.persistence.spi.JoinTable)

Aggregations

ReturningBuilder (com.blazebit.persistence.ReturningBuilder)1 CTENode (com.blazebit.persistence.impl.query.CTENode)1 CollectionUpdateModificationQuerySpecification (com.blazebit.persistence.impl.query.CollectionUpdateModificationQuerySpecification)1 ExtendedQuerySupport (com.blazebit.persistence.spi.ExtendedQuerySupport)1 JoinTable (com.blazebit.persistence.spi.JoinTable)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 SingularAttribute (javax.persistence.metamodel.SingularAttribute)1