use of com.blazebit.persistence.spi.ExtendedQuerySupport in project blaze-persistence by Blazebit.
the class AbstractDeleteCollectionCriteriaBuilder 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;
// Prepare a Map<EntityAlias.idColumnName, CollectionAlias.idColumnName>
// This is used to replace references to id columns properly in the final sql query
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();
if (joinTable == null) {
throw new IllegalStateException("Deleting inverse collections is not supported!");
}
int joinTableIndex = SqlUtils.indexOfTableName(sql, joinTable.getTableName());
String collectionAlias = SqlUtils.extractAlias(sql, joinTableIndex + joinTable.getTableName().length());
String tableToDelete = joinTable.getTableName();
String tablePrefix = mainQuery.dbmsDialect.getDeleteJoinStyle() == DeleteJoinStyle.FROM ? collectionAlias : tableToDelete;
Map<String, String> columnExpressionRemappings = new HashMap<>(joinTable.getIdColumnMappings().size());
List<String> joinTableIdColumns = new ArrayList<>();
if (joinTable.getKeyColumnMappings() != null) {
for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
joinTableIdColumns.add(entry.getKey());
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + collectionAlias + "." + entry.getValue() + ")", tablePrefix + "." + entry.getKey());
}
}
String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
if (discriminatorColumnCheck != null) {
columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
}
for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
joinTableIdColumns.add(entry.getKey());
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + ownerAlias + "." + entry.getValue() + ")", tablePrefix + "." + entry.getKey());
}
for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + targetAlias + "." + entry.getValue() + ")", 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(", ");
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());
}
return new CollectionDeleteModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled(), tableToDelete, collectionAlias, joinTableIdColumns.toArray(new String[0]), false, getDeleteExampleQuery(), columnExpressionRemappings);
}
use of com.blazebit.persistence.spi.ExtendedQuerySupport in project blaze-persistence by Blazebit.
the class AbstractInsertCollectionCriteriaBuilder 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);
Set<JoinNode> keyRestrictedLeftJoins = getKeyRestrictedLeftJoins();
List<String> keyRestrictedLeftJoinAliases = getKeyRestrictedLeftJoinAliases(baseQuery, keyRestrictedLeftJoins, Collections.EMPTY_SET);
List<EntityFunctionNode> entityFunctionNodes = getEntityFunctionNodes(baseQuery);
boolean isEmbedded = this instanceof ReturningBuilder;
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;
ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
Query insertExampleQuery = getInsertExampleQuery();
String insertExampleSql = extendedQuerySupport.getSql(em, insertExampleQuery);
String ownerAlias = extendedQuerySupport.getSqlAlias(em, insertExampleQuery, entityAlias);
String targetAlias = extendedQuerySupport.getSqlAlias(em, insertExampleQuery, JoinManager.COLLECTION_DML_BASE_QUERY_ALIAS);
JoinTable joinTable = mainQuery.jpaProvider.getJoinTable(entityType, collectionName);
int joinTableIndex = SqlUtils.indexOfTableName(insertExampleSql, joinTable.getTableName());
String collectionAlias = SqlUtils.extractAlias(insertExampleSql, joinTableIndex + joinTable.getTableName().length());
String[] selectItemExpressions = SqlUtils.getSelectItemExpressions(insertExampleSql, SqlUtils.indexOfSelect(insertExampleSql));
// 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<>(selectItemExpressions.length);
String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
if (discriminatorColumnCheck != null) {
columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
}
if (joinTable.getKeyColumnMappings() != null) {
for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
columnExpressionRemappings.put(collectionAlias + "." + entry.getValue(), entry.getKey());
}
}
for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
columnExpressionRemappings.put(ownerAlias + "." + entry.getValue(), entry.getKey());
}
for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
columnExpressionRemappings.put(targetAlias + "." + entry.getValue(), entry.getKey());
}
int cutoffColumns = 0;
StringBuilder insertSqlSb = new StringBuilder();
insertSqlSb.append("insert into ").append(joinTable.getTableName()).append("(");
for (String selectItemExpression : selectItemExpressions) {
String columnExpression = columnExpressionRemappings.get(selectItemExpression.trim());
// It should never be null, but the workaround for https://hibernate.atlassian.net/browse/HHH-13045 requires us to filter out the entity fetch columns
if (columnExpression == null) {
cutoffColumns++;
} else {
insertSqlSb.append(columnExpression).append(',');
}
}
insertSqlSb.setCharAt(insertSqlSb.length() - 1, ')');
return new CollectionInsertModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, keyRestrictedLeftJoinAliases, entityFunctionNodes, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, getInsertExecutorQuery(), insertSqlSb.toString(), cutoffColumns, getForeignKeyParticipatingQueries(), mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled());
}
use of com.blazebit.persistence.spi.ExtendedQuerySupport in project blaze-persistence by Blazebit.
the class BaseUpdateCriteriaBuilderImpl 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;
List<String> setColumns = getSetColumns();
ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
Map<String, String> aliasMapping = new TreeMap<>();
JoinNode rootNode = joinManager.getRoots().get(0);
String[] idColumns = null;
String tableToUpdate = null;
String tableAlias = null;
if ((joinManager.getRoots().size() > 1 || rootNode.hasChildNodes()) && mainQuery.dbmsDialect.getUpdateJoinStyle() != UpdateJoinStyle.NONE) {
String sql = getService(ExtendedQuerySupport.class).getSql(em, baseQuery);
if (SqlUtils.indexOfSelect(sql) != -1) {
idColumns = getIdColumns(getMetamodel().getManagedType(ExtendedManagedType.class, entityType));
int fromIndex = SqlUtils.indexOfFrom(sql);
int tableStartIndex = fromIndex + SqlUtils.FROM.length();
int tableEndIndex = sql.indexOf(" ", tableStartIndex);
tableToUpdate = sql.substring(tableStartIndex, tableEndIndex);
tableAlias = extendedQuerySupport.getSqlAlias(em, baseQuery, entityAlias);
for (String idColumn : idColumns) {
aliasMapping.put(tableAlias + "." + idColumn, "tmp.c" + aliasMapping.size());
}
SqlUtils.buildAliasMappingForTopLevelSelects(extendedQuerySupport.getSql(em, baseQuery), "tmp", aliasMapping);
}
}
return new UpdateModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled(), tableToUpdate, tableAlias, idColumns, setColumns, getForeignKeyParticipatingQueries(), aliasMapping, getUpdateExampleQuery());
}
use of com.blazebit.persistence.spi.ExtendedQuerySupport 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);
}
Aggregations