use of org.hibernate.sql.ast.tree.expression.Expression in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitInListPredicate.
@Override
public Predicate visitInListPredicate(SqmInListPredicate<?> predicate) {
// handling for "expansion"
if (predicate.getListExpressions().size() == 1) {
final SqmExpression<?> sqmExpression = predicate.getListExpressions().get(0);
if (sqmExpression instanceof SqmParameter) {
final SqmParameter<?> sqmParameter = (SqmParameter<?>) sqmExpression;
if (sqmParameter.allowMultiValuedBinding()) {
final Predicate specialCase = processInListWithSingleParameter(predicate, sqmParameter);
if (specialCase != null) {
return specialCase;
}
}
}
}
// otherwise - no special case...
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
inferrableTypeAccessStack.push(() -> {
for (SqmExpression<?> listExpression : predicate.getListExpressions()) {
final MappingModelExpressible<?> mapping = determineValueMapping(listExpression, fromClauseIndex);
if (mapping != null) {
return mapping;
}
}
return null;
});
final Expression testExpression;
try {
testExpression = (Expression) predicate.getTestExpression().accept(this);
} finally {
inferrableTypeAccessStack.pop();
}
final InListPredicate inPredicate = new InListPredicate(testExpression, predicate.isNegated(), getBooleanType());
inferrableTypeAccessStack.push(() -> determineValueMapping(predicate.getTestExpression(), fromClauseIndex));
try {
for (SqmExpression<?> expression : predicate.getListExpressions()) {
inPredicate.addExpression((Expression) expression.accept(this));
}
} finally {
inferrableTypeAccessStack.pop();
}
return inPredicate;
}
use of org.hibernate.sql.ast.tree.expression.Expression in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitBinaryArithmeticExpression.
@Override
public Object visitBinaryArithmeticExpression(SqmBinaryArithmetic<?> expression) {
SqmExpression<?> leftOperand = expression.getLeftHandOperand();
SqmExpression<?> rightOperand = expression.getRightHandOperand();
boolean durationToRight = isDuration(rightOperand.getNodeType());
TypeConfiguration typeConfiguration = getCreationContext().getMappingMetamodel().getTypeConfiguration();
TemporalType temporalTypeToLeft = typeConfiguration.getSqlTemporalType(leftOperand.getNodeType());
TemporalType temporalTypeToRight = typeConfiguration.getSqlTemporalType(rightOperand.getNodeType());
boolean temporalTypeSomewhereToLeft = adjustedTimestamp != null || temporalTypeToLeft != null;
if (temporalTypeToLeft != null && durationToRight) {
if (adjustmentScale != null || negativeAdjustment) {
// we can't distribute a scale over a date/timestamp
throw new SemanticException("scalar multiplication of temporal value");
}
}
if (durationToRight && temporalTypeSomewhereToLeft) {
return transformDurationArithmetic(expression);
} else if (temporalTypeToLeft != null && temporalTypeToRight != null) {
return transformDatetimeArithmetic(expression);
} else {
// Infer one operand type through the other
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
inferrableTypeAccessStack.push(() -> determineValueMapping(rightOperand, fromClauseIndex));
final Expression lhs = toSqlExpression(leftOperand.accept(this));
inferrableTypeAccessStack.pop();
inferrableTypeAccessStack.push(() -> determineValueMapping(leftOperand, fromClauseIndex));
final Expression rhs = toSqlExpression(rightOperand.accept(this));
inferrableTypeAccessStack.pop();
if (durationToRight && appliedByUnit != null) {
return new BinaryArithmeticExpression(lhs, expression.getOperator(), rhs, // we always get a Long value back
(BasicValuedMapping) appliedByUnit.getNodeType());
} else {
return new BinaryArithmeticExpression(lhs, expression.getOperator(), rhs, getExpressionType(expression));
}
}
}
use of org.hibernate.sql.ast.tree.expression.Expression in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitBasicValuedPath.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqmPath
@Override
public Expression visitBasicValuedPath(SqmBasicValuedSimplePath<?> sqmPath) {
final BasicValuedPathInterpretation<?> path = prepareReusablePath(sqmPath, () -> BasicValuedPathInterpretation.from(sqmPath, this, this, jpaQueryComplianceEnabled));
Expression result = path;
if (isDuration(sqmPath.getNodeType())) {
// Durations are stored (at least by default)
// in a NUMERIC column in seconds with fractional
// seconds in the decimal places
// which we need to convert to the given unit
//
// This does not work at all for a Duration
// mapped to a VARCHAR column, in which case
// we would need to parse the weird format
// defined by java.time.Duration (a bit hard
// to do without some custom function).
// Nor does it work for databases which have
// a well-defined INTERVAL type, but that is
// something we could implement.
// first let's apply the propagated scale
Expression scaledExpression = applyScale(toSqlExpression(path));
if (adjustedTimestamp != null) {
if (appliedByUnit != null) {
throw new IllegalStateException();
}
// we're adding this variable duration to the
// given date or timestamp, producing an
// adjusted date or timestamp
result = timestampadd().expression((ReturnableType<?>) adjustedTimestampType, new DurationUnit(SECOND, basicType(Long.class)), scaledExpression, adjustedTimestamp);
} else if (appliedByUnit != null) {
// we're applying the 'by unit' operator,
// producing a literal scalar value, so
// we must convert this duration from
// nanoseconds to the given unit
JdbcMappingContainer durationType = scaledExpression.getExpressionType();
Duration duration;
if (durationType.getJdbcMappings().get(0).getJdbcType().isInterval()) {
// For interval types, we need to extract the epoch for integer arithmetic for the 'by unit' operator
duration = new Duration(extractEpoch(scaledExpression), SECOND, (BasicValuedMapping) durationType);
} else {
// The absolute value of the expression is in seconds
// as the fractional seconds are in the fraction part as can be seen in DurationJavaType
duration = new Duration(scaledExpression, SECOND, (BasicValuedMapping) durationType);
}
TemporalUnit appliedUnit = appliedByUnit.getUnit().getUnit();
BasicValuedMapping scalarType = (BasicValuedMapping) appliedByUnit.getNodeType();
result = new Conversion(duration, appliedUnit, scalarType);
} else {
// a "bare" Duration value in nanoseconds
result = scaledExpression;
}
}
return withTreatRestriction(result, sqmPath);
}
use of org.hibernate.sql.ast.tree.expression.Expression in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitPluralAttributeSizeFunction.
@Override
public Expression visitPluralAttributeSizeFunction(SqmCollectionSize function) {
final SqmPath<?> pluralPath = function.getPluralPath();
prepareReusablePath(pluralPath, () -> null);
final TableGroup parentTableGroup = getFromClauseAccess().getTableGroup(pluralPath.getNavigablePath().getParent());
assert parentTableGroup != null;
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) parentTableGroup.getModelPart().findSubPart(pluralPath.getNavigablePath().getUnaliasedLocalName(), null);
assert pluralAttributeMapping != null;
final QuerySpec subQuerySpec = new QuerySpec(false);
pushProcessingState(new SqlAstQueryPartProcessingStateImpl(subQuerySpec, getCurrentProcessingState(), this, currentClauseStack::getCurrent, false));
try {
final TableGroup tableGroup = pluralAttributeMapping.createRootTableGroup(true, pluralPath.getNavigablePath(), null, () -> subQuerySpec::applyPredicate, this, creationContext);
pluralAttributeMapping.applyBaseRestrictions(subQuerySpec::applyPredicate, tableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
getFromClauseAccess().registerTableGroup(pluralPath.getNavigablePath(), tableGroup);
registerPluralTableGroupParts(tableGroup);
subQuerySpec.getFromClause().addRoot(tableGroup);
final AbstractSqmSelfRenderingFunctionDescriptor functionDescriptor = (AbstractSqmSelfRenderingFunctionDescriptor) creationContext.getSessionFactory().getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor("count");
final BasicType<Integer> integerType = creationContext.getMappingMetamodel().getTypeConfiguration().getBasicTypeForJavaType(Integer.class);
final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(functionDescriptor.getName(), functionDescriptor, Collections.singletonList(new QueryLiteral<>(1, integerType)), null, integerType, integerType);
subQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, expression));
subQuerySpec.applyPredicate(pluralAttributeMapping.getKeyDescriptor().generateJoinPredicate(parentTableGroup, tableGroup, getSqlExpressionResolver(), creationContext));
} finally {
popProcessingStateStack();
}
return subQuerySpec;
}
use of org.hibernate.sql.ast.tree.expression.Expression in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method createCorrelatedAggregateSubQuery.
protected Expression createCorrelatedAggregateSubQuery(AbstractSqmSpecificPluralPartPath<?> pluralPartPath, boolean index, String function) {
prepareReusablePath(pluralPartPath.getLhs(), () -> null);
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) determineValueMapping(pluralPartPath.getPluralDomainPath());
final FromClauseAccess parentFromClauseAccess = getFromClauseAccess();
final QuerySpec subQuerySpec = new QuerySpec(false);
pushProcessingState(new SqlAstQueryPartProcessingStateImpl(subQuerySpec, getCurrentProcessingState(), this, currentClauseStack::getCurrent, false));
try {
final TableGroup tableGroup = pluralAttributeMapping.createRootTableGroup(true, pluralPartPath.getNavigablePath(), null, () -> subQuerySpec::applyPredicate, this, creationContext);
pluralAttributeMapping.applyBaseRestrictions(subQuerySpec::applyPredicate, tableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
getFromClauseAccess().registerTableGroup(pluralPartPath.getNavigablePath(), tableGroup);
registerPluralTableGroupParts(tableGroup);
subQuerySpec.getFromClause().addRoot(tableGroup);
final AbstractSqmSelfRenderingFunctionDescriptor functionDescriptor = (AbstractSqmSelfRenderingFunctionDescriptor) creationContext.getSessionFactory().getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor(function);
final CollectionPart collectionPart = index ? pluralAttributeMapping.getIndexDescriptor() : pluralAttributeMapping.getElementDescriptor();
final ModelPart modelPart;
if (collectionPart instanceof EntityAssociationMapping) {
modelPart = ((EntityAssociationMapping) collectionPart).getKeyTargetMatchPart();
} else {
modelPart = collectionPart;
}
final List<Expression> arguments = new ArrayList<>(1);
final NavigablePath navigablePath = pluralPartPath.getNavigablePath();
final int jdbcTypeCount = modelPart.getJdbcTypeCount();
final List<Expression> tupleElements;
if (jdbcTypeCount == 1) {
tupleElements = arguments;
} else {
tupleElements = new ArrayList<>(jdbcTypeCount);
}
modelPart.forEachSelectable((selectionIndex, selectionMapping) -> tupleElements.add(new ColumnReference(tableGroup.resolveTableReference(navigablePath, selectionMapping.getContainingTableExpression()), selectionMapping, creationContext.getSessionFactory())));
if (jdbcTypeCount != 1) {
arguments.add(new SqlTuple(tupleElements, modelPart));
}
final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(functionDescriptor.getName(), functionDescriptor, arguments, null, (ReturnableType<?>) functionDescriptor.getReturnTypeResolver().resolveFunctionReturnType(() -> null, arguments).getJdbcMapping(), modelPart);
subQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, expression));
NavigablePath parent = pluralPartPath.getPluralDomainPath().getNavigablePath().getParent();
subQuerySpec.applyPredicate(pluralAttributeMapping.getKeyDescriptor().generateJoinPredicate(parentFromClauseAccess.findTableGroup(parent), tableGroup, getSqlExpressionResolver(), creationContext));
} finally {
popProcessingStateStack();
}
return subQuerySpec;
}
Aggregations