use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class ExecuteWithoutIdTableHelper method createIdMatchingSubQuerySpec.
public static QuerySpec createIdMatchingSubQuerySpec(NavigablePath navigablePath, TableReference rootTableReference, Predicate predicate, EntityPersister rootEntityPersister, SqlExpressionResolver sqlExpressionResolver, SessionFactoryImplementor sessionFactory) {
/*
* `select root_id from root_table where {predicate}
*/
final QuerySpec matchingIdSelect = new QuerySpec(false, 1);
final StandardTableGroup matchingIdSelectTableGroup = new StandardTableGroup(true, navigablePath, rootEntityPersister, rootTableReference.getIdentificationVariable(), rootTableReference, null, sessionFactory);
matchingIdSelect.getFromClause().addRoot(matchingIdSelectTableGroup);
rootEntityPersister.getIdentifierMapping().forEachSelectable((columnIndex, selection) -> {
final ColumnReference columnReference = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(SqlExpressionResolver.createColumnReferenceKey(rootTableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(rootTableReference, selection, sessionFactory));
final SqlSelection sqlSelection = new SqlSelectionImpl(// irrelevant
0, 0, columnReference);
matchingIdSelect.getSelectClause().addSqlSelection(sqlSelection);
});
matchingIdSelect.applyPredicate(predicate);
return matchingIdSelect;
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class InsertExecutionDelegate method insertTable.
private void insertTable(String tableExpression, String[] keyColumns, boolean nullableTable, ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
final List<Assignment> assignments = assignmentsByTable.get(updatingTableReference);
if (nullableTable && (assignments == null || assignments.isEmpty())) {
// no assignments for this table - skip it
return;
}
final NamedTableReference dmlTargetTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
final QuerySpec querySpec = new QuerySpec(true);
final TableGroupImpl temporaryTableGroup = new TableGroupImpl(updatingTableGroup.getNavigablePath(), null, new NamedTableReference(insertStatement.getTargetTable().getTableExpression(), updatingTableReference.getIdentificationVariable(), false, sessionFactory), entityDescriptor);
querySpec.getFromClause().addRoot(temporaryTableGroup);
final InsertStatement insertStatement = new InsertStatement(dmlTargetTableReference);
insertStatement.setSourceSelectStatement(querySpec);
if (assignments != null && !assignments.isEmpty()) {
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 String targetKeyColumnName = keyColumns[0];
final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityDescriptor.getEntityPersister();
final IdentifierGenerator identifierGenerator = entityPersister.getIdentifierGenerator();
final boolean needsKeyInsert;
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
needsKeyInsert = true;
} else if (identifierGenerator instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) identifierGenerator).getOptimizer();
// If the generator uses an optimizer, we have to generate the identifiers for the new rows
needsKeyInsert = optimizer != null && optimizer.getIncrementSize() > 1;
} else {
needsKeyInsert = false;
}
if (needsKeyInsert && insertStatement.getTargetColumnReferences().stream().noneMatch(c -> targetKeyColumnName.equals(c.getColumnExpression()))) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
insertStatement.addTargetColumnReferences(new ColumnReference(dmlTargetTableReference.getIdentificationVariable(), targetKeyColumnName, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory));
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), identifierMapping, sessionFactory)));
}
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final JdbcInsert jdbcInsert = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildInsertTranslator(sessionFactory, insertStatement).translate(null, executionContext.getQueryOptions());
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 TableBasedInsertHandler method resolveDelegate.
private ExecutionDelegate resolveDelegate(DomainQueryExecutionContext executionContext) {
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(getSqmInsertStatement().getTarget().getEntityName());
final MultiTableSqmMutationConverter converterDelegate = new MultiTableSqmMutationConverter(entityDescriptor, getSqmInsertStatement(), getSqmInsertStatement().getTarget(), domainParameterXref, executionContext.getQueryOptions(), executionContext.getSession().getLoadQueryInfluencers(), executionContext.getQueryParameterBindings(), sessionFactory);
final TableGroup insertingTableGroup = converterDelegate.getMutatingTableGroup();
final Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions;
if (domainParameterXref.getSqmParameterCount() == 0) {
parameterResolutions = Collections.emptyMap();
} else {
parameterResolutions = new IdentityHashMap<>();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// visit the insertion target using our special converter, collecting
// information about the target paths
final List<Assignment> targetPathColumns = new ArrayList<>();
final Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions = new LinkedHashMap<>();
final NamedTableReference entityTableReference = new NamedTableReference(entityTable.getTableExpression(), TemporaryTable.DEFAULT_ALIAS, true, sessionFactory);
final InsertStatement insertStatement = new InsertStatement(entityTableReference);
final BaseSqmToSqlAstConverter.AdditionalInsertValues additionalInsertValues = converterDelegate.visitInsertionTargetPaths((assigable, columnReferences) -> {
insertStatement.addTargetColumnReferences(columnReferences);
targetPathColumns.add(new Assignment(assigable, (Expression) assigable));
}, sqmInsertStatement, entityDescriptor, insertingTableGroup, (sqmParameter, mappingType, jdbcParameters) -> {
parameterResolutions.computeIfAbsent(sqmParameter, k -> new ArrayList<>(1)).add(jdbcParameters);
paramTypeResolutions.put(sqmParameter, mappingType);
});
if (sqmInsertStatement instanceof SqmInsertSelectStatement) {
final QueryPart queryPart = converterDelegate.visitQueryPart(((SqmInsertSelectStatement<?>) sqmInsertStatement).getSelectQueryPart());
queryPart.visitQuerySpecs(querySpec -> {
if (additionalInsertValues.applySelections(querySpec, sessionFactory)) {
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
final ColumnReference columnReference = new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory);
insertStatement.getTargetColumnReferences().set(insertStatement.getTargetColumnReferences().size() - 1, columnReference);
targetPathColumns.set(targetPathColumns.size() - 1, new Assignment(columnReference, columnReference));
} else if (entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) entityDescriptor.getIdentifierGenerator()).getOptimizer();
if (optimizer != null && optimizer.getIncrementSize() > 1) {
if (!sessionFactory.getJdbcServices().getDialect().supportsWindowFunctions()) {
return;
}
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
final ColumnReference columnReference = new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory);
insertStatement.getTargetColumnReferences().add(columnReference);
targetPathColumns.add(new Assignment(columnReference, columnReference));
final BasicType<Integer> rowNumberType = sessionFactory.getTypeConfiguration().getBasicTypeForJavaType(Integer.class);
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new Over<>(new SelfRenderingFunctionSqlAstExpression("row_number", (appender, args, walker) -> appender.appendSql("row_number()"), Collections.emptyList(), rowNumberType, rowNumberType), Collections.emptyList(), Collections.emptyList())));
}
}
});
insertStatement.setSourceSelectStatement(queryPart);
} else {
// Add the row number column if there is one
final IdentifierGenerator generator = entityDescriptor.getIdentifierGenerator();
final BasicType<?> rowNumberType;
if (generator instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) generator).getOptimizer();
if (optimizer != null && optimizer.getIncrementSize() > 1) {
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
rowNumberType = (BasicType<?>) rowNumberColumn.getJdbcMapping();
final ColumnReference columnReference = new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory);
insertStatement.getTargetColumnReferences().add(columnReference);
targetPathColumns.add(new Assignment(columnReference, columnReference));
} else {
rowNumberType = null;
}
} else {
rowNumberType = null;
}
final List<SqmValues> sqmValuesList = ((SqmInsertValuesStatement<?>) sqmInsertStatement).getValuesList();
final List<Values> valuesList = new ArrayList<>(sqmValuesList.size());
for (int i = 0; i < sqmValuesList.size(); i++) {
final Values values = converterDelegate.visitValues(sqmValuesList.get(i));
additionalInsertValues.applyValues(values);
if (rowNumberType != null) {
values.getExpressions().add(new QueryLiteral<>(i + 1, rowNumberType));
}
valuesList.add(values);
}
insertStatement.setValuesList(valuesList);
}
converterDelegate.pruneTableGroupJoins();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// cross-reference the TableReference by alias. The TableGroup already
// cross-references it by name, but the ColumnReference only has the alias
final Map<String, TableReference> tableReferenceByAlias = CollectionHelper.mapOfSize(insertingTableGroup.getTableReferenceJoins().size() + 1);
collectTableReference(insertingTableGroup.getPrimaryTableReference(), tableReferenceByAlias::put);
for (int i = 0; i < insertingTableGroup.getTableReferenceJoins().size(); i++) {
collectTableReference(insertingTableGroup.getTableReferenceJoins().get(i), tableReferenceByAlias::put);
}
return new InsertExecutionDelegate(sqmInsertStatement, converterDelegate, entityTable, afterUseAction, sessionUidAccess, domainParameterXref, insertingTableGroup, tableReferenceByAlias, targetPathColumns, insertStatement, parameterResolutions, paramTypeResolutions, executionContext);
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class AbstractSqlAstTranslator method determineLateralEmulationPredicate.
protected Predicate determineLateralEmulationPredicate(TableGroup tableGroup) {
if (tableGroup.getPrimaryTableReference() instanceof QueryPartTableReference) {
final QueryPartTableReference tableReference = (QueryPartTableReference) tableGroup.getPrimaryTableReference();
final List<String> columnNames = tableReference.getColumnNames();
final List<ColumnReference> columnReferences = new ArrayList<>(columnNames.size());
final List<ColumnReference> subColumnReferences = new ArrayList<>(columnNames.size());
final QueryPart queryPart = tableReference.getQueryPart();
for (String columnName : columnNames) {
columnReferences.add(new ColumnReference(tableReference, columnName, false, null, null, null, sessionFactory));
}
// The following optimization only makes sense if the necessary features are supported natively
if ((columnReferences.size() == 1 || supportsRowValueConstructorSyntax()) && supportsDistinctFromPredicate()) {
// ... x(c) on x.c is not distinct from (... fetch first 1 rows only)
if (queryPart.getFetchClauseType() == FetchClauseType.ROWS_ONLY && queryPart.getFetchClauseExpression() instanceof QueryLiteral<?> && Integer.valueOf(1).equals(((QueryLiteral<?>) queryPart.getFetchClauseExpression()).getLiteralValue())) {
return new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, queryPart);
}
}
// ... x(c) on exists(select x.c intersect ...)
if (supportsIntersect()) {
final QuerySpec lhsReferencesQuery = new QuerySpec(false);
for (ColumnReference columnReference : columnReferences) {
lhsReferencesQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
}
final List<QueryPart> queryParts = new ArrayList<>(2);
queryParts.add(lhsReferencesQuery);
queryParts.add(queryPart);
return new ExistsPredicate(new QueryGroup(false, SetOperator.INTERSECT, queryParts), false, getBooleanType());
}
// Double nested sub-query rendering if nothing else works
// We try to avoid this as much as possible as it is not very efficient and some DBs don't like it
// when a correlation happens in a sub-query that is not a direct child
// ... x(c) on exists(select 1 from (...) synth_(c) where x.c = synth_.c)
final QueryPartTableGroup subTableGroup = new QueryPartTableGroup(tableGroup.getNavigablePath(), (TableGroupProducer) tableGroup.getModelPart(), queryPart, "synth_", columnNames, false, true, sessionFactory);
for (String columnName : columnNames) {
subColumnReferences.add(new ColumnReference(subTableGroup.getPrimaryTableReference(), columnName, false, null, null, null, sessionFactory));
}
final QuerySpec existsQuery = new QuerySpec(false, 1);
existsQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new QueryLiteral<>(1, getIntegerType())));
existsQuery.getFromClause().addRoot(subTableGroup);
existsQuery.applyPredicate(new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, new SqlTuple(subColumnReferences, tableGroup.getModelPart())));
return new ExistsPredicate(existsQuery, false, getBooleanType());
}
return null;
}
use of org.hibernate.sql.results.internal.SqlSelectionImpl in project hibernate-orm by hibernate.
the class LoaderSelectBuilder method generateSubSelect.
private QueryPart generateSubSelect(PluralAttributeMapping attributeMapping, TableGroup rootTableGroup, SubselectFetch subselect, int jdbcTypeCount, LoaderSqlAstCreationState creationState, SessionFactoryImplementor sessionFactory) {
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final QuerySpec subQuery = new QuerySpec(false);
final QuerySpec loadingSqlAst = subselect.getLoadingSqlAst();
// todo (6.0) : we need to find the owner's TableGroup in the `loadingSqlAst`
final TableGroup ownerTableGroup = subselect.getOwnerTableGroup();
// transfer the from-clause
loadingSqlAst.getFromClause().visitRoots(subQuery.getFromClause()::addRoot);
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver();
final NavigablePath navigablePath = ownerTableGroup.getNavigablePath().append(attributeMapping.getAttributeName());
fkDescriptor.visitTargetSelectables((valuesPosition, selection) -> {
// for each column, resolve a SqlSelection and add it to the sub-query select-clause
final TableReference tableReference = ownerTableGroup.resolveTableReference(navigablePath, selection.getContainingTableExpression());
final Expression expression = sqlExpressionResolver.resolveSqlExpression(createColumnReferenceKey(tableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(tableReference, selection, sessionFactory));
subQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(valuesPosition + 1, valuesPosition, expression));
});
// transfer the restriction
subQuery.applyPredicate(loadingSqlAst.getWhereClauseRestrictions());
return subQuery;
}
Aggregations