use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.
the class AbstractSqlAstTranslator method renderCommaSeparatedSelectExpression.
protected final void renderCommaSeparatedSelectExpression(Iterable<? extends SqlAstNode> expressions, Iterable<String> aliases) {
String separator = NO_SEPARATOR;
final Iterator<String> aliasIterator = aliases.iterator();
for (SqlAstNode expression : expressions) {
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple(expression);
if (sqlTuple != null) {
for (Expression e : sqlTuple.getExpressions()) {
appendSql(separator);
renderSelectExpression(e);
separator = COMA_SEPARATOR;
}
} else if (expression instanceof Expression) {
appendSql(separator);
renderSelectExpression((Expression) expression);
} else {
appendSql(separator);
expression.accept(this);
}
separator = COMA_SEPARATOR;
append(WHITESPACE);
append(aliasIterator.next());
}
}
use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.
the class AbstractSqlAstTranslator method visitRelationalPredicate.
@Override
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
// todo (6.0) : do we want to allow multi-valued parameters in a relational predicate?
// yes means we'd have to support dynamically converting this predicate into
// an IN predicate or an OR predicate
//
// NOTE: JPA does not define support for multi-valued parameters here.
//
// If we decide to support that ^^ we should validate that *both* sides of the
// predicate are multi-valued parameters. because...
// well... its stupid :)
final SqlTuple lhsTuple;
final SqlTuple rhsTuple;
if ((lhsTuple = SqlTupleContainer.getSqlTuple(comparisonPredicate.getLeftHandExpression())) != null) {
final Expression rhsExpression = comparisonPredicate.getRightHandExpression();
final boolean all;
final QueryPart subquery;
// Handle emulation of quantified comparison
if (rhsExpression instanceof QueryPart) {
subquery = (QueryPart) rhsExpression;
all = true;
} else if (rhsExpression instanceof Every) {
subquery = ((Every) rhsExpression).getSubquery();
all = true;
} else if (rhsExpression instanceof Any) {
subquery = ((Any) rhsExpression).getSubquery();
all = false;
} else {
subquery = null;
all = false;
}
final ComparisonOperator operator = comparisonPredicate.getOperator();
if (lhsTuple.getExpressions().size() == 1) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
if (subquery == null) {
renderComparison(lhsTuple.getExpressions().get(0), operator, SqlTupleContainer.getSqlTuple(comparisonPredicate.getRightHandExpression()).getExpressions().get(0));
} else {
renderComparison(lhsTuple.getExpressions().get(0), operator, rhsExpression);
}
} else if (subquery != null && !supportsRowValueConstructorSyntaxInQuantifiedPredicates()) {
// For quantified relational comparisons, we can do an optimized emulation
if (supportsRowValueConstructorSyntax() && all) {
switch(operator) {
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
case GREATER_THAN:
case GREATER_THAN_OR_EQUAL:
{
emulateQuantifiedTupleSubQueryPredicate(comparisonPredicate, subquery, lhsTuple, operator);
return;
}
}
}
emulateSubQueryRelationalRestrictionPredicate(comparisonPredicate, all, subquery, lhsTuple, this::renderSelectTupleComparison, all ? operator.negated() : operator);
} else if (!supportsRowValueConstructorSyntax()) {
rhsTuple = SqlTupleContainer.getSqlTuple(rhsExpression);
assert rhsTuple != null;
// Some DBs like Oracle support tuples only for the IN subquery predicate
if ((operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL) && supportsRowValueConstructorSyntaxInInSubQuery()) {
comparisonPredicate.getLeftHandExpression().accept(this);
if (operator == ComparisonOperator.NOT_EQUAL) {
appendSql(" not");
}
appendSql(" in(");
renderExpressionsAsSubquery(rhsTuple.getExpressions());
appendSql(CLOSE_PARENTHESIS);
} else {
emulateTupleComparison(lhsTuple.getExpressions(), rhsTuple.getExpressions(), operator, true);
}
} else {
renderComparison(comparisonPredicate.getLeftHandExpression(), operator, rhsExpression);
}
} else if ((rhsTuple = SqlTupleContainer.getSqlTuple(comparisonPredicate.getRightHandExpression())) != null) {
final Expression lhsExpression = comparisonPredicate.getLeftHandExpression();
if (lhsExpression instanceof QueryGroup) {
if (rhsTuple.getExpressions().size() == 1) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
renderComparison(lhsExpression, comparisonPredicate.getOperator(), rhsTuple.getExpressions().get(0));
} else if (supportsRowValueConstructorSyntax()) {
renderComparison(lhsExpression, comparisonPredicate.getOperator(), comparisonPredicate.getRightHandExpression());
} else {
emulateSubQueryRelationalRestrictionPredicate(comparisonPredicate, false, (QueryGroup) lhsExpression, rhsTuple, this::renderSelectTupleComparison, // Since we switch the order of operands, we have to invert the operator
comparisonPredicate.getOperator().invert());
}
} else {
throw new IllegalStateException("Unsupported tuple comparison combination. LHS is neither a tuple nor a tuple subquery but RHS is a tuple: " + comparisonPredicate);
}
} else {
renderComparison(comparisonPredicate.getLeftHandExpression(), comparisonPredicate.getOperator(), comparisonPredicate.getRightHandExpression());
}
}
use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.
the class LoaderSelectBuilder method applyRestriction.
private void applyRestriction(QuerySpec rootQuerySpec, NavigablePath rootNavigablePath, TableGroup rootTableGroup, ModelPart modelPart, int numberColumns, Consumer<JdbcParameter> jdbcParameterConsumer, LoaderSqlAstCreationState sqlAstCreationState) {
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final NavigablePath navigablePath = rootNavigablePath.append(modelPart.getNavigableRole().getNavigableName());
if (numberColumns == 1) {
modelPart.forEachSelectable((columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference(navigablePath, selection.getContainingTableExpression());
final ColumnReference columnRef = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(createColumnReferenceKey(tableReference, selection.getSelectionExpression()), p -> new ColumnReference(tableReference, selection, creationContext.getSessionFactory()));
if (numberOfKeysToLoad == 1) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl(selection.getJdbcMapping());
jdbcParameterConsumer.accept(jdbcParameter);
rootQuerySpec.applyPredicate(new ComparisonPredicate(columnRef, ComparisonOperator.EQUAL, jdbcParameter));
} else {
final InListPredicate predicate = new InListPredicate(columnRef);
for (int i = 0; i < numberOfKeysToLoad; i++) {
for (int j = 0; j < numberColumns; j++) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl(columnRef.getJdbcMapping());
jdbcParameterConsumer.accept(jdbcParameter);
predicate.addExpression(jdbcParameter);
}
}
rootQuerySpec.applyPredicate(predicate);
}
});
} else {
final List<ColumnReference> columnReferences = new ArrayList<>(numberColumns);
modelPart.forEachSelectable((columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference(navigablePath, selection.getContainingTableExpression());
columnReferences.add((ColumnReference) sqlExpressionResolver.resolveSqlExpression(createColumnReferenceKey(tableReference, selection.getSelectionExpression()), p -> new ColumnReference(tableReference, selection, creationContext.getSessionFactory())));
});
final SqlTuple tuple = new SqlTuple(columnReferences, modelPart);
final InListPredicate predicate = new InListPredicate(tuple);
for (int i = 0; i < numberOfKeysToLoad; i++) {
final List<JdbcParameter> tupleParams = new ArrayList<>(numberColumns);
for (int j = 0; j < numberColumns; j++) {
final ColumnReference columnReference = columnReferences.get(j);
final JdbcParameter jdbcParameter = new JdbcParameterImpl(columnReference.getJdbcMapping());
jdbcParameterConsumer.accept(jdbcParameter);
tupleParams.add(jdbcParameter);
}
final SqlTuple paramTuple = new SqlTuple(tupleParams, modelPart);
predicate.addExpression(paramTuple);
}
rootQuerySpec.applyPredicate(predicate);
}
}
use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.
the class InPredicateRestrictionProducer method produceRestriction.
@Override
public InListPredicate produceRestriction(List<?> matchingIdValues, EntityMappingType entityDescriptor, int valueIndex, ModelPart valueModelPart, TableReference mutatingTableReference, Supplier<Consumer<SelectableConsumer>> columnsToMatchVisitationSupplier, ExecutionContext executionContext) {
assert matchingIdValues != null;
assert !matchingIdValues.isEmpty();
final SessionFactoryImplementor sessionFactory = executionContext.getSession().getFactory();
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
final int idColumnCount = identifierMapping.getJdbcTypeCount();
assert idColumnCount > 0;
final InListPredicate predicate;
if (idColumnCount == 1) {
final BasicValuedModelPart basicIdMapping = (BasicValuedModelPart) identifierMapping;
final String idColumn = basicIdMapping.getSelectionExpression();
final Expression inFixture = new ColumnReference(mutatingTableReference, idColumn, // id columns cannot be formulas and cannot have custom read and write expressions
false, null, null, basicIdMapping.getJdbcMapping(), sessionFactory);
predicate = new InListPredicate(inFixture);
matchingIdValues.forEach(matchingId -> predicate.addExpression(new JdbcLiteral<>(matchingId, basicIdMapping.getJdbcMapping())));
} else {
final List<ColumnReference> columnReferences = new ArrayList<>(idColumnCount);
final List<JdbcMapping> jdbcMappings = new ArrayList<>(idColumnCount);
identifierMapping.forEachSelectable((columnIndex, selection) -> {
columnReferences.add(new ColumnReference(mutatingTableReference, selection, sessionFactory));
jdbcMappings.add(selection.getJdbcMapping());
});
final Expression inFixture = new SqlTuple(columnReferences, identifierMapping);
predicate = new InListPredicate(inFixture);
matchingIdValues.forEach(matchingId -> {
assert matchingId instanceof Object[];
final Object[] matchingIdParts = (Object[]) matchingId;
final List<JdbcLiteral<?>> tupleParts = new ArrayList<>(idColumnCount);
for (int p = 0; p < matchingIdParts.length; p++) {
tupleParts.add(new JdbcLiteral<>(matchingIdParts[p], jdbcMappings.get(p)));
}
predicate.addExpression(new SqlTuple(tupleParts, identifierMapping));
});
}
return predicate;
}
use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.
the class AbstractCteMutationHandler method createIdSubQueryPredicate.
protected Predicate createIdSubQueryPredicate(List<? extends Expression> lhsExpressions, CteStatement idSelectCte, ModelPart fkModelPart, SessionFactoryImplementor factory) {
final NamedTableReference idSelectTableReference = new NamedTableReference(idSelectCte.getCteTable().getTableExpression(), CTE_TABLE_IDENTIFIER, false, factory);
final Junction predicate = new Junction(Junction.Nature.CONJUNCTION);
final List<CteColumn> cteColumns = idSelectCte.getCteTable().getCteColumns();
final int size = lhsExpressions.size();
final QuerySpec subQuery = new QuerySpec(false, 1);
subQuery.getFromClause().addRoot(new CteTableGroup(idSelectTableReference));
final SelectClause subQuerySelectClause = subQuery.getSelectClause();
if (fkModelPart == null) {
for (int i = 0; i < size; i++) {
final CteColumn cteColumn = cteColumns.get(i);
subQuerySelectClause.addSqlSelection(new SqlSelectionImpl(i + 1, i, new ColumnReference(idSelectTableReference, cteColumn.getColumnExpression(), cteColumn.getJdbcMapping(), factory)));
}
} else {
fkModelPart.forEachSelectable((selectionIndex, selectableMapping) -> {
subQuerySelectClause.addSqlSelection(new SqlSelectionImpl(selectionIndex + 1, selectionIndex, new ColumnReference(idSelectTableReference, selectableMapping.getSelectionExpression(), selectableMapping.getJdbcMapping(), factory)));
});
}
final Expression lhs;
if (lhsExpressions.size() == 1) {
lhs = lhsExpressions.get(0);
} else {
lhs = new SqlTuple(lhsExpressions, null);
}
predicate.add(new InSubQueryPredicate(lhs, subQuery, false));
return predicate;
}
Aggregations