use of org.hibernate.sql.ast.tree.select.SelectClause in project hibernate-orm by hibernate.
the class SmokeTests method testConvertedHqlInterpretation.
@Test
public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
scope.inTransaction(session -> {
final JdbcTypeRegistry jdbcTypeRegistry = session.getFactory().getTypeConfiguration().getJdbcTypeRegistry();
final QueryImplementor<Gender> query = session.createQuery("select e.gender from SimpleEntity e", Gender.class);
final SqmQueryImplementor<Gender> hqlQuery = (SqmQueryImplementor<Gender>) query;
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
final StandardSqmTranslator<SelectStatement> sqmConverter = new StandardSqmTranslator<>(sqmStatement, hqlQuery.getQueryOptions(), ((QuerySqmImpl<?>) hqlQuery).getDomainParameterXref(), query.getParameterBindings(), session.getLoadQueryInfluencers(), scope.getSessionFactory(), true);
final SqmTranslation<SelectStatement> sqmInterpretation = sqmConverter.translate();
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
assertThat(fromClause.getRoots().size(), is(1));
final TableGroup rootTableGroup = fromClause.getRoots().get(0);
assertThat(rootTableGroup.getPrimaryTableReference(), notNullValue());
assertThat(rootTableGroup.getPrimaryTableReference().getTableId(), is("mapping_simple_entity"));
assertThat(rootTableGroup.getTableReferenceJoins().size(), is(0));
assertThat(rootTableGroup.getTableGroupJoins().isEmpty(), is(true));
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `s1`. The primary table reference is always suffixed as `_0`
assertThat(rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is("s1_0"));
final SelectClause selectClause = sqlAst.getQuerySpec().getSelectClause();
assertThat(selectClause.getSqlSelections().size(), is(1));
final SqlSelection sqlSelection = selectClause.getSqlSelections().get(0);
assertThat(sqlSelection.getJdbcResultSetIndex(), is(1));
assertThat(sqlSelection.getValuesArrayPosition(), is(0));
assertThat(sqlSelection.getJdbcValueExtractor(), notNullValue());
assertThat(sqlSelection, instanceOf(SqlSelectionImpl.class));
final Expression selectedExpression = sqlSelection.getExpression();
assertThat(selectedExpression, instanceOf(ColumnReference.class));
final ColumnReference columnReference = (ColumnReference) selectedExpression;
assertThat(columnReference.renderSqlFragment(scope.getSessionFactory()), is("s1_0.gender"));
final JdbcMappingContainer selectedExpressible = selectedExpression.getExpressionType();
assertThat(selectedExpressible, instanceOf(BasicTypeImpl.class));
final BasicTypeImpl<?> basicType = (BasicTypeImpl<?>) selectedExpressible;
assertThat(basicType.getJavaTypeDescriptor().getJavaTypeClass(), AssignableMatcher.assignableTo(Integer.class));
assertThat(basicType.getJdbcType(), is(jdbcTypeRegistry.getDescriptor(Types.TINYINT)));
assertThat(sqlAst.getDomainResultDescriptors().size(), is(1));
final DomainResult<?> domainResult = sqlAst.getDomainResultDescriptors().get(0);
assertThat(domainResult, instanceOf(BasicResult.class));
final BasicResult<?> scalarDomainResult = (BasicResult<?>) domainResult;
assertThat(scalarDomainResult.getAssembler(), instanceOf(BasicResultAssembler.class));
final BasicResultAssembler<?> assembler = (BasicResultAssembler<?>) scalarDomainResult.getAssembler();
assertThat(assembler.getValueConverter(), notNullValue());
assertThat(assembler.getValueConverter(), instanceOf(OrdinalEnumValueConverter.class));
final NavigablePath expectedSelectedPath = new NavigablePath(SimpleEntity.class.getName(), "e").append("gender");
assertThat(domainResult.getNavigablePath(), equalTo(expectedSelectedPath));
assertThat(domainResult, instanceOf(BasicResult.class));
// ScalarDomainResultImpl creates and caches the assembler at its creation.
// this just gets access to that cached one
final DomainResultAssembler<?> resultAssembler = domainResult.createResultAssembler(null, null);
assertThat(resultAssembler, instanceOf(BasicResultAssembler.class));
final BasicValueConverter<?, ?> valueConverter = ((BasicResultAssembler<?>) resultAssembler).getValueConverter();
assertThat(valueConverter, notNullValue());
assertThat(valueConverter, instanceOf(OrdinalEnumValueConverter.class));
final JdbcSelect jdbcSelectOperation = new StandardSqlAstTranslator<JdbcSelect>(session.getSessionFactory(), sqlAst).translate(null, QueryOptions.NONE);
assertThat(jdbcSelectOperation.getSql(), is("select s1_0.gender from mapping_simple_entity s1_0"));
});
}
use of org.hibernate.sql.ast.tree.select.SelectClause in project hibernate-orm by hibernate.
the class SmokeTests method testSimpleHqlInterpretation.
@Test
public void testSimpleHqlInterpretation(SessionFactoryScope scope) {
scope.inTransaction(session -> {
final QueryImplementor<String> query = session.createQuery("select e.name from SimpleEntity e", String.class);
final SqmQueryImplementor<String> hqlQuery = (SqmQueryImplementor<String>) query;
final SqmSelectStatement<String> sqmStatement = (SqmSelectStatement<String>) hqlQuery.getSqmStatement();
final StandardSqmTranslator<SelectStatement> sqmConverter = new StandardSqmTranslator<>(sqmStatement, hqlQuery.getQueryOptions(), ((QuerySqmImpl<?>) hqlQuery).getDomainParameterXref(), query.getParameterBindings(), session.getLoadQueryInfluencers(), scope.getSessionFactory(), true);
final SqmTranslation<SelectStatement> sqmInterpretation = sqmConverter.translate();
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
assertThat(fromClause.getRoots().size(), is(1));
final TableGroup rootTableGroup = fromClause.getRoots().get(0);
assertThat(rootTableGroup.getPrimaryTableReference(), notNullValue());
assertThat(rootTableGroup.getPrimaryTableReference().getTableId(), is("mapping_simple_entity"));
assertThat(rootTableGroup.getTableReferenceJoins().size(), is(0));
assertThat(rootTableGroup.getTableGroupJoins().isEmpty(), is(true));
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `s1`. The primary table reference is always suffixed as `_0`
assertThat(rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is("s1_0"));
final SelectClause selectClause = sqlAst.getQuerySpec().getSelectClause();
assertThat(selectClause.getSqlSelections().size(), is(1));
final SqlSelection sqlSelection = selectClause.getSqlSelections().get(0);
assertThat(sqlSelection.getJdbcResultSetIndex(), is(1));
assertThat(sqlSelection.getValuesArrayPosition(), is(0));
assertThat(sqlSelection.getJdbcValueExtractor(), notNullValue());
final JdbcSelect jdbcSelectOperation = new StandardSqlAstTranslator<JdbcSelect>(session.getSessionFactory(), sqlAst).translate(null, QueryOptions.NONE);
assertThat(jdbcSelectOperation.getSql(), is("select s1_0.name from mapping_simple_entity s1_0"));
});
}
use of org.hibernate.sql.ast.tree.select.SelectClause in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitQuerySpec.
@Override
public QuerySpec visitQuerySpec(SqmQuerySpec<?> sqmQuerySpec) {
final boolean topLevel = getProcessingStateStack().isEmpty();
final QuerySpec sqlQuerySpec = new QuerySpec(topLevel, sqmQuerySpec.getFromClause().getNumberOfRoots());
final SqmSelectClause selectClause = sqmQuerySpec.getSelectClause();
final Predicate originalAdditionalRestrictions = additionalRestrictions;
additionalRestrictions = null;
final boolean trackAliasedNodePositions;
if (trackSelectionsForGroup) {
trackAliasedNodePositions = true;
} else if (sqmQuerySpec.getOrderByClause() != null && sqmQuerySpec.getOrderByClause().hasPositionalSortItem()) {
trackAliasedNodePositions = true;
} else if (sqmQuerySpec.hasPositionalGroupItem()) {
trackAliasedNodePositions = true;
} else {
// Since JPA Criteria queries can use the same expression object in order or group by items,
// we need to track the positions to be able to replace the expression in the items with alias references
// Also see #resolveGroupOrOrderByExpression for more details
trackAliasedNodePositions = statement.getQuerySource() == SqmQuerySource.CRITERIA && (sqmQuerySpec.getOrderByClause() != null || !sqmQuerySpec.getGroupByClauseExpressions().isEmpty());
}
final SqlAstProcessingState processingState;
if (trackAliasedNodePositions) {
processingState = new SqlAstQueryPartProcessingStateImpl(sqlQuerySpec, getCurrentProcessingState(), this, r -> new SqmAliasedNodePositionTracker(r, selectClause.getSelections()), currentClauseStack::getCurrent, deduplicateSelectionItems);
} else {
processingState = new SqlAstQueryPartProcessingStateImpl(sqlQuerySpec, getCurrentProcessingState(), this, currentClauseStack::getCurrent, deduplicateSelectionItems);
}
final SqmQueryPart<?> sqmQueryPart = currentSqmQueryPart;
final boolean originalDeduplicateSelectionItems = deduplicateSelectionItems;
currentSqmQueryPart = sqmQuerySpec;
// In sub-queries, we can never deduplicate the selection items as that might change semantics
deduplicateSelectionItems = false;
pushProcessingState(processingState);
queryTransformers.push(new ArrayList<>());
try {
// we want to visit the from-clause first
visitFromClause(sqmQuerySpec.getFromClause());
visitSelectClause(selectClause);
final SqmWhereClause whereClause = sqmQuerySpec.getWhereClause();
if (whereClause != null) {
sqlQuerySpec.applyPredicate(visitWhereClause(whereClause.getPredicate()));
}
sqlQuerySpec.setGroupByClauseExpressions(visitGroupByClause(sqmQuerySpec.getGroupByClauseExpressions()));
if (sqmQuerySpec.getHavingClausePredicate() != null) {
sqlQuerySpec.setHavingClauseRestrictions(visitHavingClause(sqmQuerySpec.getHavingClausePredicate()));
}
visitOrderByOffsetAndFetch(sqmQuerySpec, sqlQuerySpec);
if (topLevel && statement instanceof SqmSelectStatement<?>) {
if (orderByFragments != null) {
orderByFragments.forEach(entry -> entry.getKey().apply(sqlQuerySpec, entry.getValue(), this));
orderByFragments = null;
}
applyCollectionFilterPredicates(sqlQuerySpec);
}
QuerySpec finalQuerySpec = sqlQuerySpec;
for (QueryTransformer transformer : queryTransformers.getCurrent()) {
finalQuerySpec = transformer.transform(cteContainer, finalQuerySpec, this);
}
return finalQuerySpec;
} finally {
if (additionalRestrictions != null) {
sqlQuerySpec.applyPredicate(additionalRestrictions);
}
additionalRestrictions = originalAdditionalRestrictions;
popProcessingStateStack();
queryTransformers.pop();
currentSqmQueryPart = sqmQueryPart;
deduplicateSelectionItems = originalDeduplicateSelectionItems;
}
}
use of org.hibernate.sql.ast.tree.select.SelectClause in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitSelectClause.
@Override
public SelectClause visitSelectClause(SqmSelectClause selectClause) {
currentClauseStack.push(Clause.SELECT);
try {
final SelectClause sqlSelectClause = currentQuerySpec().getSelectClause();
if (selectClause == null) {
final SqmFrom<?, ?> implicitSelection = determineImplicitSelection((SqmQuerySpec<?>) currentSqmQueryPart);
visitSelection(new SqmSelection<>(implicitSelection, implicitSelection.nodeBuilder()));
} else {
super.visitSelectClause(selectClause);
sqlSelectClause.makeDistinct(selectClause.isDistinct());
}
return sqlSelectClause;
} finally {
currentClauseStack.pop();
}
}
use of org.hibernate.sql.ast.tree.select.SelectClause in project hibernate-orm by hibernate.
the class AbstractSqlAstTranslator method renderQueryGroup.
protected void renderQueryGroup(QueryGroup queryGroup, boolean renderOrderByAndOffsetFetchClause) {
final QueryPart queryPartForRowNumbering = this.queryPartForRowNumbering;
final int queryPartForRowNumberingClauseDepth = this.queryPartForRowNumberingClauseDepth;
final boolean needsSelectAliases = this.needsSelectAliases;
try {
String queryGroupAlias = null;
// See the field documentation of queryPartForRowNumbering etc. for an explanation about this
final QueryPart currentQueryPart = queryPartStack.getCurrent();
if (currentQueryPart != null && queryPartForRowNumberingClauseDepth != clauseStack.depth()) {
this.queryPartForRowNumbering = null;
this.queryPartForRowNumberingClauseDepth = -1;
this.needsSelectAliases = false;
}
final boolean needsParenthesis = !queryGroup.isRoot();
if (needsParenthesis) {
appendSql(OPEN_PARENTHESIS);
}
// order by and offset fetch clause, so we must do row counting on the query group level
if (queryPartForRowNumbering == queryGroup || additionalWherePredicate != null && !additionalWherePredicate.isEmpty()) {
this.needsSelectAliases = true;
queryGroupAlias = "grp_" + queryGroupAliasCounter + '_';
queryGroupAliasCounter++;
appendSql("select ");
appendSql(queryGroupAlias);
appendSql(".* ");
final SelectClause firstSelectClause = queryGroup.getFirstQuerySpec().getSelectClause();
final List<SqlSelection> sqlSelections = firstSelectClause.getSqlSelections();
final int sqlSelectionsSize = sqlSelections.size();
// We need this synthetic select clause to properly render the ORDER BY within the OVER clause
// of the row numbering functions
final SelectClause syntheticSelectClause = new SelectClause(sqlSelectionsSize);
for (int i = 0; i < sqlSelectionsSize; i++) {
syntheticSelectClause.addSqlSelection(new SqlSelectionImpl(i + 1, i, new ColumnReference(queryGroupAlias, "c" + i, false, null, null, getIntegerType(), null)));
}
renderRowNumberingSelectItems(syntheticSelectClause, queryPartForRowNumbering);
appendSql(" from (");
}
queryPartStack.push(queryGroup);
final List<QueryPart> queryParts = queryGroup.getQueryParts();
final String setOperatorString = ' ' + queryGroup.getSetOperator().sqlString() + ' ';
String separator = "";
for (int i = 0; i < queryParts.size(); i++) {
appendSql(separator);
queryParts.get(i).accept(this);
separator = setOperatorString;
}
if (renderOrderByAndOffsetFetchClause) {
visitOrderBy(queryGroup.getSortSpecifications());
visitOffsetFetchClause(queryGroup);
}
if (queryGroupAlias != null) {
appendSql(") ");
appendSql(queryGroupAlias);
if (additionalWherePredicate != null && !additionalWherePredicate.isEmpty()) {
visitWhereClause(additionalWherePredicate);
}
}
if (needsParenthesis) {
appendSql(CLOSE_PARENTHESIS);
}
} finally {
queryPartStack.pop();
this.queryPartForRowNumbering = queryPartForRowNumbering;
this.queryPartForRowNumberingClauseDepth = queryPartForRowNumberingClauseDepth;
this.needsSelectAliases = needsSelectAliases;
}
}
Aggregations