use of org.hibernate.sql.ast.spi.SqlSelection in project hibernate-orm by hibernate.
the class QueryLiteral method createDomainResult.
@Override
public DomainResult<T> createDomainResult(String resultVariable, DomainResultCreationState creationState) {
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(this, type.getMappedType().getMappedJavaType(), creationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration());
return new BasicResult(sqlSelection.getValuesArrayPosition(), resultVariable, type.getMappedType().getMappedJavaType());
}
use of org.hibernate.sql.ast.spi.SqlSelection in project hibernate-orm by hibernate.
the class AbstractCollectionPersister method selectFragment.
/**
* Generate a list of collection index, key and element columns
*/
@Override
public String selectFragment(String alias, String columnSuffix) {
final PluralAttributeMapping attributeMapping = getAttributeMapping();
final QuerySpec rootQuerySpec = new QuerySpec(true);
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(rootQuerySpec, new SqlAliasBaseManager(), new SimpleFromClauseAccessImpl(), LockOptions.NONE, (fetchParent, querySpec, creationState) -> new ArrayList<>(), true, getFactory());
final NavigablePath entityPath = new NavigablePath(attributeMapping.getRootPathName());
final TableGroup rootTableGroup = attributeMapping.createRootTableGroup(true, entityPath, null, () -> p -> {
}, new SqlAliasBaseConstant(alias), sqlAstCreationState.getSqlExpressionResolver(), sqlAstCreationState.getFromClauseAccess(), getFactory());
rootQuerySpec.getFromClause().addRoot(rootTableGroup);
sqlAstCreationState.getFromClauseAccess().registerTableGroup(entityPath, rootTableGroup);
attributeMapping.createDomainResult(entityPath, rootTableGroup, null, sqlAstCreationState);
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final java.util.List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
int i = 0;
for (String keyAlias : keyColumnAliases) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), keyAlias + columnSuffix)));
i++;
}
if (hasIndex) {
for (String indexAlias : indexColumnAliases) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), indexAlias + columnSuffix)));
i++;
}
}
if (hasIdentifier) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), identifierColumnAlias + columnSuffix)));
i++;
}
for (int columnIndex = 0; i < sqlSelections.size(); i++, columnIndex++) {
final SqlSelection sqlSelection = sqlSelections.get(i);
sqlSelections.set(i, new SqlSelectionImpl(sqlSelection.getValuesArrayPosition(), sqlSelection.getJdbcResultSetIndex(), new AliasedExpression(sqlSelection.getExpression(), elementColumnAliases[columnIndex] + columnSuffix)));
}
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;
}
use of org.hibernate.sql.ast.spi.SqlSelection in project hibernate-orm by hibernate.
the class AggregateWindowEmulationQueryTransformer method transform.
@Override
public QuerySpec transform(CteContainer cteContainer, QuerySpec querySpec, SqmToSqlAstConverter converter) {
final SessionFactoryImplementor factory = converter.getCreationContext().getSessionFactory();
final QuerySpec outerQuerySpec = new QuerySpec(querySpec.isRoot());
final String identifierVariable = "hhh_";
final NavigablePath navigablePath = new NavigablePath(identifierVariable, identifierVariable);
final SelectClause selectClause = outerQuerySpec.getSelectClause();
final QuerySpec subQuerySpec = querySpec.asSubQuery();
final SelectClause subSelectClause = subQuerySpec.getSelectClause();
final List<SqlSelection> subSelections = subSelectClause.getSqlSelections();
final List<String> columnNames = new ArrayList<>(subSelections.size());
// A map to find the select item position for an expression
// which is needed to decide if we need to introduce synthetic select items
// for group by items, since these group by items are migrated to the outer query
final Map<Expression, Integer> selectionMapping = new HashMap<>(subSelections.size());
// for the QueryPartTableGroup within which the sub query spec is embedded
for (int i = 0; i < subSelections.size(); i++) {
final BasicValuedMapping mapping = (BasicValuedMapping) subSelections.get(i).getExpressionType();
final String columnName = "col" + i;
final ColumnReference columnReference = new ColumnReference(identifierVariable, columnName, false, null, null, mapping.getJdbcMapping(), factory);
final Expression expression = subSelections.get(i).getExpression();
final Expression finalExpression;
if (expression == windowFunction) {
finalExpression = new SelfRenderingAggregateFunctionSqlAstExpression("min", (sqlAppender, sqlAstArguments, walker1) -> {
sqlAppender.appendSql("min(");
sqlAstArguments.get(0).accept(walker1);
sqlAppender.append(')');
}, Collections.singletonList(columnReference), null, (ReturnableType<?>) mapping.getMappedType(), expression.getExpressionType());
} else {
finalExpression = columnReference;
selectionMapping.put(expression, i);
}
columnNames.add(columnName);
selectClause.addSqlSelection(new ResolvedSqlSelection(i + 1, i, finalExpression, (BasicType<Object>) mapping.getJdbcMapping()));
}
// Migrate the group by clause to the outer query
// and push group by expressions into the partition by clause of the window function
final List<Expression> groupByExpressions = new ArrayList<>(subQuerySpec.getGroupByClauseExpressions().size());
for (Expression groupByClauseExpression : subQuerySpec.getGroupByClauseExpressions()) {
final Expression realExpression;
final Expression outerGroupByExpression;
if (groupByClauseExpression instanceof SqlSelectionExpression) {
final SqlSelection selection = ((SqlSelectionExpression) groupByClauseExpression).getSelection();
outerGroupByExpression = new SqlSelectionExpression(selectClause.getSqlSelections().get(selection.getValuesArrayPosition()));
realExpression = selection.getExpression();
} else {
if (groupByClauseExpression instanceof SqmPathInterpretation<?>) {
realExpression = ((SqmPathInterpretation<?>) groupByClauseExpression).getSqlExpression();
} else {
realExpression = groupByClauseExpression;
}
final Integer position = selectionMapping.get(realExpression);
if (position == null) {
// Group by something that has no corresponding selection item,
// so we need to introduce an intermediate selection item
final int valuesPosition = selectClause.getSqlSelections().size();
final String columnName = "col" + valuesPosition;
final JdbcMapping jdbcMapping = realExpression.getExpressionType().getJdbcMappings().get(0);
final ColumnReference columnReference = new ColumnReference(identifierVariable, columnName, false, null, null, jdbcMapping, factory);
final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection(subValuesPosition + 1, subValuesPosition, realExpression, (BasicType<Object>) jdbcMapping);
columnNames.add(columnName);
subSelectClause.addSqlSelection(subSelection);
outerGroupByExpression = columnReference;
selectionMapping.put(realExpression, subValuesPosition);
} else {
outerGroupByExpression = new SqlSelectionExpression(selectClause.getSqlSelections().get(position));
}
}
windowFunction.getPartitions().add(realExpression);
groupByExpressions.add(outerGroupByExpression);
}
outerQuerySpec.setGroupByClauseExpressions(groupByExpressions);
subQuerySpec.setGroupByClauseExpressions(null);
// Migrate the having clause to the outer query
if (subQuerySpec.getHavingClauseRestrictions() != null) {
final Predicate predicate = new ExpressionReplacementWalker() {
@Override
protected <X extends SqlAstNode> X replaceExpression(X expression) {
if (expression instanceof Literal || expression instanceof JdbcParameter) {
return expression;
}
final Expression outerExpression;
if (expression instanceof SqlSelectionExpression) {
final SqlSelection selection = ((SqlSelectionExpression) expression).getSelection();
outerExpression = selectClause.getSqlSelections().get(selection.getValuesArrayPosition()).getExpression();
} else {
final Expression realExpression;
if (expression instanceof SqmPathInterpretation<?>) {
realExpression = ((SqmPathInterpretation<?>) expression).getSqlExpression();
} else {
realExpression = (Expression) expression;
}
final Integer position = selectionMapping.get(realExpression);
if (position == null) {
// An expression that has no corresponding selection item,
// so we need to introduce an intermediate selection item
final int valuesPosition = selectClause.getSqlSelections().size();
final String columnName = "col" + valuesPosition;
final JdbcMapping jdbcMapping = realExpression.getExpressionType().getJdbcMappings().get(0);
final ColumnReference columnReference = new ColumnReference(identifierVariable, columnName, false, null, null, jdbcMapping, factory);
final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection(subValuesPosition + 1, subValuesPosition, realExpression, (BasicType<Object>) jdbcMapping);
columnNames.add(columnName);
subSelectClause.addSqlSelection(subSelection);
outerExpression = columnReference;
selectionMapping.put(realExpression, subValuesPosition);
} else {
outerExpression = selectClause.getSqlSelections().get(position).getExpression();
}
}
return (X) outerExpression;
}
}.replaceExpressions(subQuerySpec.getHavingClauseRestrictions());
outerQuerySpec.setHavingClauseRestrictions(predicate);
subQuerySpec.setHavingClauseRestrictions(null);
}
// Migrate the order by clause to the outer query
if (subQuerySpec.hasSortSpecifications()) {
for (SortSpecification sortSpecification : subQuerySpec.getSortSpecifications()) {
final Expression sortExpression = sortSpecification.getSortExpression();
final Expression outerSortExpression;
if (sortExpression instanceof SqlSelectionExpression) {
final SqlSelection selection = ((SqlSelectionExpression) sortExpression).getSelection();
outerSortExpression = new SqlSelectionExpression(selectClause.getSqlSelections().get(selection.getValuesArrayPosition()));
} else {
final Expression realExpression;
if (sortExpression instanceof SqmPathInterpretation<?>) {
realExpression = ((SqmPathInterpretation<?>) sortExpression).getSqlExpression();
} else {
realExpression = sortExpression;
}
final Integer position = selectionMapping.get(realExpression);
if (position == null) {
// Group by something that has no corresponding selection item,
// so we need to introduce an intermediate selection item
final int valuesPosition = selectClause.getSqlSelections().size();
final String columnName = "col" + valuesPosition;
final JdbcMapping jdbcMapping = realExpression.getExpressionType().getJdbcMappings().get(0);
final ColumnReference columnReference = new ColumnReference(identifierVariable, columnName, false, null, null, jdbcMapping, factory);
final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection(subValuesPosition + 1, subValuesPosition, realExpression, (BasicType<Object>) jdbcMapping);
columnNames.add(columnName);
subSelectClause.addSqlSelection(subSelection);
outerSortExpression = columnReference;
selectionMapping.put(realExpression, subValuesPosition);
} else {
outerSortExpression = new SqlSelectionExpression(selectClause.getSqlSelections().get(position));
}
}
outerQuerySpec.addSortSpecification(new SortSpecification(outerSortExpression, sortSpecification.getSortOrder(), sortSpecification.getNullPrecedence()));
}
subQuerySpec.getSortSpecifications().clear();
}
// We need to add selection items for the expressions we order by to the sub query spec.
final int selectionOffset = columnNames.size();
// Collect the sorting column references so we can apply the filter later
final List<ColumnReference> sortingColumns = new ArrayList<>(withinGroup.size());
for (int i = 0; i < withinGroup.size(); i++) {
final int valueIndex = selectionOffset + i;
final Expression sortExpression = withinGroup.get(i).getSortExpression();
final BasicValuedMapping mapping = (BasicValuedMapping) sortExpression.getExpressionType();
final String columnName = "col" + valueIndex;
final int oldValueIndex = subSelectClause.getSqlSelections().size();
columnNames.add(columnName);
subSelectClause.addSqlSelection(new ResolvedSqlSelection(oldValueIndex + 1, oldValueIndex, sortExpression, (BasicType<Object>) mapping.getJdbcMapping()));
sortingColumns.add(new ColumnReference(identifierVariable, columnName, false, null, null, mapping.getJdbcMapping(), factory));
}
if (arguments != null) {
// So we add a filter to the outer query so we can extract the rank
switch(arguments.size()) {
case 0:
break;
case 1:
outerQuerySpec.applyPredicate(new ComparisonPredicate(sortingColumns.get(0), ComparisonOperator.EQUAL, (Expression) arguments.get(0)));
break;
default:
outerQuerySpec.applyPredicate(new ComparisonPredicate(new SqlTuple(sortingColumns, null), ComparisonOperator.EQUAL, new SqlTuple((List<? extends Expression>) (List<?>) arguments, null)));
}
}
final QueryPartTableGroup queryPartTableGroup = new QueryPartTableGroup(navigablePath, null, subQuerySpec, identifierVariable, columnNames, false, true, factory);
outerQuerySpec.getFromClause().addRoot(queryPartTableGroup);
// Migrate the offset/fetch clause
outerQuerySpec.setOffsetClauseExpression(subQuerySpec.getOffsetClauseExpression());
outerQuerySpec.setFetchClauseExpression(subQuerySpec.getFetchClauseExpression(), subQuerySpec.getFetchClauseType());
subQuerySpec.setOffsetClauseExpression(null);
subQuerySpec.setFetchClauseExpression(null, null);
return outerQuerySpec;
}
use of org.hibernate.sql.ast.spi.SqlSelection 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;
}
use of org.hibernate.sql.ast.spi.SqlSelection in project hibernate-orm by hibernate.
the class SqlAstQueryPartProcessingStateImpl method resolveSqlSelection.
@Override
public SqlSelection resolveSqlSelection(Expression expression, JavaType<?> javaType, TypeConfiguration typeConfiguration) {
final SqlSelection existing;
if (sqlSelectionMap == null) {
sqlSelectionMap = new HashMap<>();
existing = null;
} else {
existing = sqlSelectionMap.get(expression);
}
if (existing != null && deduplicateSelectionItems) {
return existing;
}
final SelectClause selectClause = ((QuerySpec) queryPart).getSelectClause();
final int valuesArrayPosition = selectClause.getSqlSelections().size();
final SqlSelection sqlSelection = expression.createSqlSelection(valuesArrayPosition + 1, valuesArrayPosition, javaType, typeConfiguration);
sqlSelectionMap.put(expression, sqlSelection);
selectClause.addSqlSelection(sqlSelection);
return sqlSelection;
}
Aggregations