use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class ExecuteWithTemporaryTableHelper method saveMatchingIdsIntoIdTable.
public static int saveMatchingIdsIntoIdTable(MultiTableSqmMutationConverter sqmConverter, Predicate suppliedPredicate, TemporaryTable idTable, Function<SharedSessionContractImplementor, String> sessionUidAccess, JdbcParameterBindings jdbcParameterBindings, ExecutionContext executionContext) {
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
final TableGroup mutatingTableGroup = sqmConverter.getMutatingTableGroup();
assert mutatingTableGroup.getModelPart() instanceof EntityMappingType;
final EntityMappingType mutatingEntityDescriptor = (EntityMappingType) mutatingTableGroup.getModelPart();
final NamedTableReference idTableReference = new NamedTableReference(idTable.getTableExpression(), InsertStatement.DEFAULT_ALIAS, false, factory);
final InsertStatement idTableInsert = new InsertStatement(idTableReference);
for (int i = 0; i < idTable.getColumns().size(); i++) {
final TemporaryTableColumn column = idTable.getColumns().get(i);
idTableInsert.addTargetColumnReferences(new ColumnReference(idTableReference, column.getColumnName(), // id columns cannot be formulas and cannot have custom read and write expressions
false, null, null, column.getJdbcMapping(), factory));
}
final QuerySpec matchingIdSelection = new QuerySpec(true, 1);
idTableInsert.setSourceSelectStatement(matchingIdSelection);
matchingIdSelection.getFromClause().addRoot(mutatingTableGroup);
mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable((jdbcPosition, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference(mutatingTableGroup.getNavigablePath(), selection.getContainingTableExpression());
matchingIdSelection.getSelectClause().addSqlSelection(new SqlSelectionImpl(jdbcPosition, jdbcPosition + 1, sqmConverter.getSqlExpressionResolver().resolveSqlExpression(SqlExpressionResolver.createColumnReferenceKey(tableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(tableReference, selection, factory))));
});
if (idTable.getSessionUidColumn() != null) {
final int jdbcPosition = matchingIdSelection.getSelectClause().getSqlSelections().size();
matchingIdSelection.getSelectClause().addSqlSelection(new SqlSelectionImpl(jdbcPosition, jdbcPosition + 1, new QueryLiteral<>(sessionUidAccess.apply(executionContext.getSession()), (BasicValuedMapping) idTable.getSessionUidColumn().getJdbcMapping())));
}
matchingIdSelection.applyPredicate(suppliedPredicate);
return saveIntoTemporaryTable(idTableInsert, jdbcParameterBindings, executionContext);
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class SimpleDeleteQueryPlan method executeUpdate.
@Override
public int executeUpdate(DomainQueryExecutionContext executionContext) {
BulkOperationCleanupAction.schedule(executionContext.getSession(), sqmDelete);
final SharedSessionContractImplementor session = executionContext.getSession();
final SessionFactoryImplementor factory = session.getFactory();
final JdbcServices jdbcServices = factory.getJdbcServices();
SqlAstTranslator<JdbcDelete> deleteTranslator = null;
if (jdbcDelete == null) {
deleteTranslator = createDeleteTranslator(executionContext);
}
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(executionContext.getQueryParameterBindings(), domainParameterXref, jdbcParamsXref, factory.getRuntimeMetamodels().getMappingMetamodel(), sqmInterpretation.getFromClauseAccess()::findTableGroup, new SqmParameterMappingModelResolutionAccess() {
@Override
@SuppressWarnings("unchecked")
public <T> MappingModelExpressible<T> getResolvedMappingModelType(SqmParameter<T> parameter) {
return (MappingModelExpressible<T>) sqmInterpretation.getSqmParameterMappingModelTypeResolutions().get(parameter);
}
}, session);
if (jdbcDelete != null && !jdbcDelete.isCompatibleWith(jdbcParameterBindings, executionContext.getQueryOptions())) {
deleteTranslator = createDeleteTranslator(executionContext);
}
if (deleteTranslator != null) {
jdbcDelete = deleteTranslator.translate(jdbcParameterBindings, executionContext.getQueryOptions());
} else {
jdbcDelete.bindFilterJdbcParameters(jdbcParameterBindings);
}
final boolean missingRestriction = sqmDelete.getWhereClause() == null || sqmDelete.getWhereClause().getPredicate() == null;
if (missingRestriction) {
assert domainParameterXref.getSqmParameterCount() == 0;
assert jdbcParamsXref.isEmpty();
}
final SqmJdbcExecutionContextAdapter executionContextAdapter = SqmJdbcExecutionContextAdapter.usingLockingAndPaging(executionContext);
SqmMutationStrategyHelper.cleanUpCollectionTables(entityDescriptor, (tableReference, attributeMapping) -> {
if (missingRestriction) {
return null;
}
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final Expression fkColumnExpression = MappingModelHelper.buildColumnReferenceExpression(fkDescriptor.getKeyPart(), null, factory);
final QuerySpec matchingIdSubQuery = new QuerySpec(false);
final MutatingTableReferenceGroupWrapper tableGroup = new MutatingTableReferenceGroupWrapper(new NavigablePath(attributeMapping.getRootPathName()), attributeMapping, sqmInterpretation.getSqlAst().getTargetTable());
final Expression fkTargetColumnExpression = MappingModelHelper.buildColumnReferenceExpression(tableGroup, fkDescriptor.getTargetPart(), sqmInterpretation.getSqlExpressionResolver(), factory);
matchingIdSubQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, fkTargetColumnExpression));
matchingIdSubQuery.getFromClause().addRoot(tableGroup);
matchingIdSubQuery.applyPredicate(sqmInterpretation.getSqlAst().getRestriction());
return new InSubQueryPredicate(fkColumnExpression, matchingIdSubQuery, false);
}, (missingRestriction ? JdbcParameterBindings.NO_BINDINGS : jdbcParameterBindings), executionContextAdapter);
return jdbcServices.getJdbcMutationExecutor().execute(jdbcDelete, jdbcParameterBindings, sql -> session.getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContextAdapter);
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class InsertExecutionDelegate method insertRootTable.
private void insertRootTable(String tableExpression, int rows, String[] keyColumns, ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator();
final List<Assignment> assignments = assignmentsByTable.get(updatingTableReference);
if ((assignments == null || assignments.isEmpty()) && !(identifierGenerator instanceof PostInsertIdentifierGenerator)) {
throw new IllegalStateException("There must be at least a single root table assignment");
}
final NamedTableReference dmlTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the SQL AST and convert it into a JdbcOperation
final QuerySpec querySpec = new QuerySpec(true);
final NamedTableReference temporaryTableReference = new NamedTableReference(insertStatement.getTargetTable().getTableExpression(), updatingTableReference.getIdentificationVariable(), false, sessionFactory);
final TableGroupImpl temporaryTableGroup = new TableGroupImpl(updatingTableGroup.getNavigablePath(), null, temporaryTableReference, entityDescriptor);
querySpec.getFromClause().addRoot(temporaryTableGroup);
final InsertStatement insertStatement = new InsertStatement(dmlTableReference);
insertStatement.setSourceSelectStatement(querySpec);
for (Assignment assignment : assignments) {
insertStatement.addTargetColumnReferences(assignment.getAssignable().getColumnReferences());
for (ColumnReference columnReference : assignment.getAssignable().getColumnReferences()) {
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), columnReference.getColumnExpression(), false, null, null, columnReference.getJdbcMapping(), sessionFactory)));
}
}
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final Map<Object, Object> entityTableToRootIdentity;
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final QuerySpec idSelectQuerySpec = new QuerySpec(true);
idSelectQuerySpec.getFromClause().addRoot(temporaryTableGroup);
final ColumnReference columnReference = new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory);
idSelectQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
idSelectQuerySpec.addSortSpecification(new SortSpecification(columnReference, SortOrder.ASCENDING));
final SelectStatement selectStatement = new SelectStatement(idSelectQuerySpec, Collections.singletonList(new BasicFetch<>(0, null, null, identifierMapping, null, FetchTiming.IMMEDIATE, null)));
final JdbcSelect jdbcSelect = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildSelectTranslator(sessionFactory, selectStatement).translate(null, executionContext.getQueryOptions());
final List<Object> list = jdbcServices.getJdbcSelectExecutor().list(jdbcSelect, JdbcParameterBindings.NO_BINDINGS, executionContext, null, ListResultsConsumer.UniqueSemantic.NONE);
entityTableToRootIdentity = new LinkedHashMap<>(list.size());
for (Object o : list) {
entityTableToRootIdentity.put(o, null);
}
querySpec.applyPredicate(new ComparisonPredicate(columnReference, ComparisonOperator.EQUAL, new JdbcParameterImpl(identifierMapping.getJdbcMapping())));
} else {
entityTableToRootIdentity = null;
if (identifierGenerator instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) identifierGenerator).getOptimizer();
// but only if the target paths don't already contain the id
if (optimizer != null && optimizer.getIncrementSize() > 1 && insertStatement.getTargetColumnReferences().stream().noneMatch(c -> keyColumns[0].equals(c.getColumnExpression()))) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final JdbcParameter rowNumber = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
final ColumnReference idColumnReference = new ColumnReference((String) null, identifierMapping, sessionFactory);
temporaryTableAssignments.add(new Assignment(idColumnReference, rootIdentity));
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, rowNumber));
final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
for (int i = 0; i < rows; i++) {
updateBindings.addBinding(rowNumber, new JdbcParameterBindingImpl(rowNumberColumn.getJdbcMapping(), i + 1));
updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), identifierGenerator.generate(executionContext.getSession(), null)));
jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
insertStatement.addTargetColumnReferences(new ColumnReference((String) null, keyColumns[0], false, null, null, identifierMapping.getJdbcMapping(), sessionFactory));
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), idColumnReference.getColumnExpression(), false, null, null, idColumnReference.getJdbcMapping(), sessionFactory)));
}
}
}
final JdbcInsert jdbcInsert = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildInsertTranslator(sessionFactory, insertStatement).translate(null, executionContext.getQueryOptions());
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
final PostInsertIdentifierGenerator generator = (PostInsertIdentifierGenerator) identifierGenerator;
final boolean generatedKeysEnabled = sessionFactory.getSessionFactoryOptions().isGetGeneratedKeysEnabled();
final InsertGeneratedIdentifierDelegate identifierDelegate = generator.getInsertGeneratedIdentifierDelegate((PostInsertIdentityPersister) entityDescriptor.getEntityPersister(), jdbcServices.getDialect(), generatedKeysEnabled);
final String finalSql = identifierDelegate.prepareIdentifierGeneratingInsert(jdbcInsert.getSql());
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final ValueBinder jdbcValueBinder = identifierMapping.getJdbcMapping().getJdbcValueBinder();
for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
final Object rootIdentity = identifierDelegate.performInsert(finalSql, executionContext.getSession(), new Binder() {
@Override
public void bindValues(PreparedStatement ps) throws SQLException {
jdbcValueBinder.bind(ps, entry.getKey(), 1, executionContext.getSession());
}
@Override
public Object getEntity() {
return null;
}
});
entry.setValue(rootIdentity);
}
final JdbcParameter entityIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
temporaryTableAssignments.add(new Assignment(new ColumnReference((String) null, identifierMapping, sessionFactory), rootIdentity));
final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, entityIdentity));
final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
updateBindings.addBinding(entityIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getKey()));
updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getValue()));
jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
} else {
jdbcServices.getJdbcMutationExecutor().execute(jdbcInsert, JdbcParameterBindings.NO_BINDINGS, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class MatchingIdSelectionHelper method generateMatchingIdSelectQuery.
/**
* @asciidoc
*
* Generates a query-spec for selecting all ids matching the restriction defined as part
* of the user's update/delete query. This query-spec is generally used:
*
* * to select all the matching ids via JDBC - see {@link MatchingIdSelectionHelper#selectMatchingIds}
* * as a sub-query restriction to insert rows into an "id table"
*/
public static QuerySpec generateMatchingIdSelectQuery(EntityMappingType targetEntityDescriptor, SqmDeleteOrUpdateStatement sqmStatement, DomainParameterXref domainParameterXref, Predicate restriction, MultiTableSqmMutationConverter sqmConverter, SessionFactoryImplementor sessionFactory) {
final EntityDomainType entityDomainType = sqmStatement.getTarget().getModel();
if (log.isTraceEnabled()) {
log.tracef("Starting generation of entity-id SQM selection - %s", entityDomainType.getHibernateEntityName());
}
final QuerySpec idSelectionQuery = new QuerySpec(true, 1);
final TableGroup mutatingTableGroup = sqmConverter.getMutatingTableGroup();
idSelectionQuery.getFromClause().addRoot(mutatingTableGroup);
targetEntityDescriptor.getIdentifierMapping().forEachSelectable((position, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference(mutatingTableGroup.getNavigablePath(), selection.getContainingTableExpression());
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(SqlExpressionResolver.createColumnReferenceKey(tableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(tableReference, selection, sessionFactory));
idSelectionQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(position, position + 1, expression));
});
idSelectionQuery.applyPredicate(restriction);
return idSelectionQuery;
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class AbstractEntityPersister method selectFragment.
@Override
public String selectFragment(String alias, String suffix) {
final QuerySpec rootQuerySpec = new QuerySpec(true);
final String rootTableName = getRootTableName();
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(rootQuerySpec, new SqlAliasBaseManager(), new SimpleFromClauseAccessImpl(), LockOptions.NONE, (fetchParent, querySpec, creationState) -> {
final List<Fetch> fetches = new ArrayList<>();
fetchParent.getReferencedMappingContainer().visitFetchables(fetchable -> {
// Ignore plural attributes
if (fetchable instanceof PluralAttributeMapping) {
return;
}
FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
final boolean selectable;
if (fetchable instanceof StateArrayContributorMapping) {
final int propertyNumber = ((StateArrayContributorMapping) fetchable).getStateArrayPosition();
final int tableNumber = getSubclassPropertyTableNumber(propertyNumber);
selectable = !isSubclassTableSequentialSelect(tableNumber) && propertySelectable[propertyNumber];
} else {
selectable = true;
}
if (fetchable instanceof BasicValuedModelPart) {
// Ignore lazy basic columns
if (fetchTiming == FetchTiming.DELAYED) {
return;
}
} else if (fetchable instanceof Association) {
final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
if (association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET) {
return;
}
// Ensure the FK comes from the root table
if (!rootTableName.equals(association.getForeignKeyDescriptor().getKeyTable())) {
return;
}
fetchTiming = FetchTiming.DELAYED;
}
if (selectable) {
final NavigablePath navigablePath = fetchParent.resolveNavigablePath(fetchable);
final Fetch fetch = fetchParent.generateFetchableFetch(fetchable, navigablePath, fetchTiming, true, null, creationState);
fetches.add(fetch);
}
}, null);
return fetches;
}, true, getFactory());
final NavigablePath entityPath = new NavigablePath(getRootPathName());
final TableGroup rootTableGroup = createRootTableGroup(true, entityPath, null, () -> p -> {
}, new SqlAliasBaseConstant(alias), sqlAstCreationState.getSqlExpressionResolver(), sqlAstCreationState.getFromClauseAccess(), getFactory());
rootQuerySpec.getFromClause().addRoot(rootTableGroup);
sqlAstCreationState.getFromClauseAccess().registerTableGroup(entityPath, rootTableGroup);
createDomainResult(entityPath, rootTableGroup, null, sqlAstCreationState);
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
int i = 0;
for (String identifierAlias : identifierAliases) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), identifierAlias + suffix)));
i++;
}
if (entityMetamodel.hasSubclasses()) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), getDiscriminatorAlias() + suffix)));
i++;
}
if (hasRowId()) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), ROWID_ALIAS + suffix)));
i++;
}
final String[] columnAliases = getSubclassColumnAliasClosure();
final String[] formulaAliases = getSubclassFormulaAliasClosure();
int columnIndex = 0;
int formulaIndex = 0;
for (; i < sqlSelections.size(); i++) {
final SqlSelection sqlSelection = sqlSelections.get(i);
final ColumnReference columnReference = (ColumnReference) sqlSelection.getExpression();
final String selectAlias;
if (!columnReference.isColumnExpressionFormula()) {
// Skip over columns that are not selectable like in the fetch generation
while (!subclassColumnSelectableClosure[columnIndex]) {
columnIndex++;
}
selectAlias = columnAliases[columnIndex++] + suffix;
} else {
selectAlias = formulaAliases[formulaIndex++] + suffix;
}
sqlSelections.set(i, new SqlSelectionImpl(sqlSelection.getValuesArrayPosition(), sqlSelection.getJdbcResultSetIndex(), new AliasedExpression(sqlSelection.getExpression(), selectAlias)));
}
final String sql = getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory().buildSelectTranslator(getFactory(), new SelectStatement(rootQuerySpec)).translate(null, QueryOptions.NONE).getSql();
final int fromIndex = sql.lastIndexOf(" from");
final String expression;
if (fromIndex != -1) {
expression = sql.substring("select ".length(), fromIndex);
} else {
expression = sql.substring("select ".length());
}
return expression;
}
Aggregations