Search in sources :

Example 51 with PathExpression

use of com.blazebit.persistence.parser.expression.PathExpression in project blaze-persistence by Blazebit.

the class JoinVisitor method getNaturalIdAttribute.

private String getNaturalIdAttribute(Expression expression) {
    // Hibernate fails to do this and instead compares the primary key with the natural key which might go by unnoticed
    if (expression instanceof PathExpression) {
        PathExpression pathExpression = (PathExpression) expression;
        visit(pathExpression, false);
        PathReference pathReference = (pathExpression).getPathReference();
        // We only attach the natural id to paths referring to entity types
        if (pathReference != null && pathReference.getField() != null && pathReference.getType() instanceof EntityType<?>) {
            JoinNode node = (JoinNode) pathReference.getBaseNode();
            // We need a parent tree node to determine the natural id attribute
            Collection<String> identifierOrUniqueKeyEmbeddedPropertyNames = metamodel.getJpaProvider().getJoinMappingPropertyNames(node.getEntityType(), null, pathReference.getField()).keySet();
            if (identifierOrUniqueKeyEmbeddedPropertyNames.size() == 1) {
                // This "fix" only works if we have a single id attribute
                String naturalIdAttribute = identifierOrUniqueKeyEmbeddedPropertyNames.iterator().next();
                ExtendedManagedType extendedManagedType = metamodel.getManagedType(ExtendedManagedType.class, (ManagedType<?>) pathReference.getType());
                if (!extendedManagedType.getIdAttribute().getName().equals(naturalIdAttribute)) {
                    // Now we finally know the natural id attribute name
                    return naturalIdAttribute;
                }
            }
        }
    }
    return null;
}
Also used : PathReference(com.blazebit.persistence.parser.expression.PathReference) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType)

Example 52 with PathExpression

use of com.blazebit.persistence.parser.expression.PathExpression in project blaze-persistence by Blazebit.

the class JoinVisitor method visit.

private void visit(PathExpression expression, boolean idRemovable) {
    Expression aliasedExpression;
    String alias = expression.getExpressions().size() == 1 ? expression.toString() : null;
    if (alias != null && !currentlyResolvingAliases.contains(alias) && (aliasedExpression = joinManager.getJoinableSelectAlias(expression, fromClause == ClauseType.SELECT, false)) != null) {
        try {
            currentlyResolvingAliases.add(alias);
            aliasedExpression.accept(this);
            // We initialize the aliased PathExpression properly
            if (aliasedExpression instanceof PathExpression) {
                PathExpression aliasedPathExpression = (PathExpression) aliasedExpression;
                if (aliasedPathExpression.isCollectionQualifiedPath()) {
                    expression.setCollectionQualifiedPath(true);
                }
                if (aliasedPathExpression.isUsedInCollectionFunction()) {
                    expression.setUsedInCollectionFunction(true);
                }
            }
        } finally {
            currentlyResolvingAliases.remove(alias);
        }
    } else if (ArrayExpression.ELEMENT_NAME.equals(alias)) {
    // We will not resolve the ArrayExpression.ELEMENT_NAME alias, this must be done in the join manager and is only allowed within an ArrayExpression
    } else {
        if (relativeExpressionPrefix != null) {
            PathExpression leftMost = ExpressionUtils.getLeftMostPathExpression(expression);
            String leftMostAlias;
            if (leftMost.getExpressions().get(0) instanceof ArrayExpression) {
                leftMostAlias = ((ArrayExpression) leftMost.getExpressions().get(0)).getBase().toString();
            } else {
                leftMostAlias = ((PropertyExpression) leftMost.getExpressions().get(0)).getProperty();
            }
            if (ArrayExpression.ELEMENT_NAME.equals(leftMostAlias)) {
                return;
            }
            JoinAliasInfo aliasInfo = (JoinAliasInfo) joinManager.getAliasManager().getAliasInfo(leftMostAlias);
            if (aliasInfo == null) {
                leftMost.getExpressions().add(0, new PropertyExpression(ArrayExpression.ELEMENT_NAME));
                return;
            }
        }
        try {
            // But allow joins if this expression was joined before already to avoid possible side-effects of implicit joining multiple times
            if (expression.getBaseNode() != null) {
            }
            joinManager.implicitJoin(expression, joinAllowed, true, joinWithObjectLeafAllowed, null, fromClause, null, currentJoinNode, currentlyResolvingAliases, false, false, joinRequired, idRemovable, false, reuseExisting);
            if (parentVisitor != null) {
                JoinNode baseNode = (JoinNode) expression.getBaseNode();
                AliasManager aliasOwner = baseNode.getAliasInfo().getAliasOwner();
                if (aliasOwner != joinManager.getAliasManager()) {
                    addParentClauseDependencies(baseNode, aliasOwner);
                }
            }
        } catch (ImplicitJoinNotAllowedException ex) {
            if (conjunctionPathExpressionFindingVisitor == null) {
                conjunctionPathExpressionFindingVisitor = new ConjunctionPathExpressionFindingVisitor();
            }
            correlationPathReplacementVisitor.addPathExpression(expression, ex, conjunctionPathExpressionFindingVisitor.isInConjunction(currentJoinNode.getOnPredicate(), expression));
        }
    }
}
Also used : PathExpression(com.blazebit.persistence.parser.expression.PathExpression) ListIndexExpression(com.blazebit.persistence.parser.expression.ListIndexExpression) Expression(com.blazebit.persistence.parser.expression.Expression) TreatExpression(com.blazebit.persistence.parser.expression.TreatExpression) ParameterExpression(com.blazebit.persistence.parser.expression.ParameterExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression) ArrayExpression(com.blazebit.persistence.parser.expression.ArrayExpression) FunctionExpression(com.blazebit.persistence.parser.expression.FunctionExpression) SubqueryExpression(com.blazebit.persistence.parser.expression.SubqueryExpression) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) PathElementExpression(com.blazebit.persistence.parser.expression.PathElementExpression) ArrayExpression(com.blazebit.persistence.parser.expression.ArrayExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression)

Example 53 with PathExpression

use of com.blazebit.persistence.parser.expression.PathExpression in project blaze-persistence by Blazebit.

the class EmbeddableSplittingVisitor method collectSplittedOffExpressions.

protected boolean collectSplittedOffExpressions(Expression expression) {
    splittedOffExpressions.clear();
    if (expressionToSplit != null) {
        JoinNode baseNode;
        String field;
        if (expressionToSplit instanceof PathExpression) {
            PathReference pathReference = ((PathExpression) expressionToSplit).getPathReference();
            baseNode = (JoinNode) pathReference.getBaseNode();
            field = pathReference.getField();
        } else if (expressionToSplit instanceof MapKeyExpression) {
            baseNode = ((JoinNode) ((MapKeyExpression) expressionToSplit).getPath().getBaseNode()).getKeyJoinNode();
            field = null;
        } else {
            // This should never happen
            return false;
        }
        String fieldPrefix = field == null ? "" : field + ".";
        ExtendedManagedType<?> managedType = metamodel.getManagedType(ExtendedManagedType.class, baseNode.getManagedType());
        Map<String, Boolean> orderedAttributes = new TreeMap<>();
        EntityType<?> ownerType;
        if ((baseNode.getParentTreeNode() == null || splitEntity && baseNode.getManagedType() instanceof EntityType<?>) && field == null) {
            ownerType = baseNode.getEntityType();
            for (SingularAttribute<?, ?> idAttribute : managedType.getIdAttributes()) {
                addAttributes(ownerType, null, fieldPrefix, "", idAttribute, orderedAttributes);
            }
        } else {
            Map<String, ? extends ExtendedAttribute<?, ?>> ownedAttributes;
            String prefix = field;
            if (baseNode.getParentTreeNode() != null && jpaProvider.getJpaMetamodelAccessor().isElementCollection(baseNode.getParentTreeNode().getAttribute())) {
                String elementCollectionPath = baseNode.getParentTreeNode().getRelationName();
                ExtendedManagedType entityManagedType = metamodel.getManagedType(ExtendedManagedType.class, baseNode.getParent().getEntityType());
                ownedAttributes = entityManagedType.getAttributes();
                if (prefix == null) {
                    prefix = elementCollectionPath;
                } else {
                    prefix = elementCollectionPath + "." + prefix;
                }
            } else {
                ownedAttributes = managedType.getOwnedSingularAttributes();
            }
            for (String embeddedPropertyPath : JpaUtils.getEmbeddedPropertyPaths((Map<String, ExtendedAttribute<?, ?>>) ownedAttributes, prefix, false, false)) {
                orderedAttributes.put(embeddedPropertyPath, Boolean.FALSE);
            }
        }
        // Signal the caller that the expression was eliminated
        if (orderedAttributes.isEmpty()) {
            return true;
        }
        for (String orderedAttribute : orderedAttributes.keySet()) {
            splittedOffExpressions.add(splittingVisitor.splitOff(expression, expressionToSplit, orderedAttribute));
        }
    }
    return false;
}
Also used : PathReference(com.blazebit.persistence.parser.expression.PathReference) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) TreeMap(java.util.TreeMap) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) EntityType(javax.persistence.metamodel.EntityType) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression)

Example 54 with PathExpression

use of com.blazebit.persistence.parser.expression.PathExpression in project blaze-persistence by Blazebit.

the class EmbeddableSplittingVisitor method visit.

@Override
public Boolean visit(MapKeyExpression expression) {
    PathExpression path = expression.getPath();
    PathReference pathReference = path.getPathReference();
    while (pathReference == null) {
        Expression aliasedExpression = ((SelectInfo) aliasManager.getAliasInfo(path.toString())).getExpression();
        if (aliasedExpression instanceof PathExpression) {
            path = (PathExpression) aliasedExpression;
            pathReference = path.getPathReference();
        } else {
            // This should never happen
            return false;
        }
    }
    JoinNode baseNode = (JoinNode) pathReference.getBaseNode();
    Attribute attr;
    if (baseNode.getParentTreeNode() != null) {
        attr = baseNode.getParentTreeNode().getAttribute();
        Type<?> t;
        if (attr instanceof MapAttribute<?, ?, ?> && ((t = ((MapAttribute<?, ?, ?>) attr).getKeyType()) instanceof EmbeddableType<?> || splitEntity && t instanceof EntityType<?>)) {
            expressionToSplit = expression;
        }
    }
    return false;
}
Also used : PathReference(com.blazebit.persistence.parser.expression.PathReference) EntityType(javax.persistence.metamodel.EntityType) MapAttribute(javax.persistence.metamodel.MapAttribute) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) ListIndexExpression(com.blazebit.persistence.parser.expression.ListIndexExpression) WhenClauseExpression(com.blazebit.persistence.parser.expression.WhenClauseExpression) Expression(com.blazebit.persistence.parser.expression.Expression) GeneralCaseExpression(com.blazebit.persistence.parser.expression.GeneralCaseExpression) TrimExpression(com.blazebit.persistence.parser.expression.TrimExpression) ParameterExpression(com.blazebit.persistence.parser.expression.ParameterExpression) ArithmeticExpression(com.blazebit.persistence.parser.expression.ArithmeticExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) TypeFunctionExpression(com.blazebit.persistence.parser.expression.TypeFunctionExpression) MapEntryExpression(com.blazebit.persistence.parser.expression.MapEntryExpression) ArrayExpression(com.blazebit.persistence.parser.expression.ArrayExpression) NullExpression(com.blazebit.persistence.parser.expression.NullExpression) FunctionExpression(com.blazebit.persistence.parser.expression.FunctionExpression) SimpleCaseExpression(com.blazebit.persistence.parser.expression.SimpleCaseExpression) SubqueryExpression(com.blazebit.persistence.parser.expression.SubqueryExpression) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) MapAttribute(javax.persistence.metamodel.MapAttribute) SingularAttribute(javax.persistence.metamodel.SingularAttribute) Attribute(javax.persistence.metamodel.Attribute) PluralAttribute(javax.persistence.metamodel.PluralAttribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute)

Example 55 with PathExpression

use of com.blazebit.persistence.parser.expression.PathExpression in project blaze-persistence by Blazebit.

the class ImplicitJoinCorrelationPathReplacementVisitor method addPathExpression.

public void addPathExpression(PathExpression pathExpression, ImplicitJoinNotAllowedException ex, boolean isInConjunction) {
    if (!pathIdentitiesToCorrelate.containsKey(pathExpression)) {
        StringBuilder sb = new StringBuilder();
        if (ex.getTreatType() != null) {
            sb.append("TREAT(");
        }
        if (isInConjunction) {
            ex.getBaseNode().appendAlias(sb, true, false);
        } else {
            String syntheticAlias = "_synthetic_" + ex.getBaseNode().getAlias();
            List<PathElementExpression> list1 = new ArrayList<>(1);
            list1.add(new PropertyExpression(syntheticAlias));
            List<PathElementExpression> list2 = new ArrayList<>(1);
            list2.add(new PropertyExpression(ex.getBaseNode().getAlias()));
            Predicate predicate = new EqPredicate(new PathExpression(list1), new PathExpression(list2));
            rootsToCorrelate.put(syntheticAlias, new RootCorrelationEntry(syntheticAlias, ex.getBaseNode().getNodeType().getJavaType(), predicate));
            sb.append(syntheticAlias);
        }
        sb.append('.');
        sb.append(ex.getJoinRelationName());
        if (ex.getTreatType() != null) {
            sb.append(" AS ").append(ex.getTreatType()).append(')');
        }
        String correlationExpression = sb.toString();
        String alias;
        CorrelationTransformEntry existingEntry = pathsToCorrelate.get(correlationExpression);
        if (existingEntry != null) {
            alias = existingEntry.alias;
        } else {
            alias = "_synth_subquery_" + pathIdentitiesToCorrelate.size();
        }
        PathExpression transformedExpression = pathExpression.copy(ExpressionCopyContext.EMPTY);
        // For now, we only support 2 levels of treats, but this obviously should be improved
        if (transformedExpression.getExpressions().get(0) instanceof TreatExpression) {
            // Only the first expression in the list can be a treat expression
            TreatExpression treatExpression = (TreatExpression) transformedExpression.getExpressions().get(0);
            if (treatExpression.getType().equals(ex.getTreatType())) {
                // The not-allowed implicit join is the one within the treat
                PathExpression pathExpressionToModify = (PathExpression) treatExpression.getExpression();
                removeMatchingJoinAttributePathElements(ex, pathExpressionToModify);
                if (pathExpressionToModify.getExpressions().isEmpty()) {
                    transformedExpression.getExpressions().set(0, new PropertyExpression(alias));
                } else {
                    throw new IllegalArgumentException("Can't transform nested TREAT expression: " + pathExpression);
                }
            } else {
                // The not-allowed implicit join happens after dereferencing the treat
                PathExpression pathExpressionToModify = (PathExpression) treatExpression.getExpression();
                // In addition, we also need to make sure the root treat alias matches the not-allowed implicit joins base node alias
                if ((ex.getBaseNode().getTreatType() == null && ex.getBaseNode().getEntityType().getName().equals(treatExpression.getType()) || ex.getBaseNode().getTreatType() != null && ex.getBaseNode().getTreatType().getName().equals(treatExpression.getType())) && pathExpressionToModify.getExpressions().size() == 1 && ex.getBaseNode().getAlias().equals(pathExpressionToModify.getExpressions().get(0).toString())) {
                    // Root treat
                    removeMatchingJoinAttributePathElements(ex, transformedExpression);
                    transformedExpression.getExpressions().add(0, new PropertyExpression(alias));
                } else {
                    removeMatchingJoinAttributePathElements(ex, pathExpressionToModify);
                    pathExpressionToModify.getExpressions().add(0, new PropertyExpression(alias));
                }
            }
        } else {
            removeMatchingJoinAttributePathElements(ex, transformedExpression);
            transformedExpression.getExpressions().add(0, new PropertyExpression(alias));
        }
        CorrelationTransformEntry correlationTransformEntry = new CorrelationTransformEntry(alias, correlationExpression, transformedExpression, isInConjunction);
        pathIdentitiesToCorrelate.put(pathExpression, correlationTransformEntry);
        if (existingEntry == null) {
            pathsToCorrelate.put(correlationExpression, correlationTransformEntry);
        }
    }
}
Also used : TreatExpression(com.blazebit.persistence.parser.expression.TreatExpression) ArrayList(java.util.ArrayList) EqPredicate(com.blazebit.persistence.parser.predicate.EqPredicate) EqPredicate(com.blazebit.persistence.parser.predicate.EqPredicate) Predicate(com.blazebit.persistence.parser.predicate.Predicate) PathElementExpression(com.blazebit.persistence.parser.expression.PathElementExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression)

Aggregations

PathExpression (com.blazebit.persistence.parser.expression.PathExpression)55 PropertyExpression (com.blazebit.persistence.parser.expression.PropertyExpression)37 PathElementExpression (com.blazebit.persistence.parser.expression.PathElementExpression)29 Expression (com.blazebit.persistence.parser.expression.Expression)27 FunctionExpression (com.blazebit.persistence.parser.expression.FunctionExpression)26 SubqueryExpression (com.blazebit.persistence.parser.expression.SubqueryExpression)22 MapKeyExpression (com.blazebit.persistence.parser.expression.MapKeyExpression)21 ArrayExpression (com.blazebit.persistence.parser.expression.ArrayExpression)20 ParameterExpression (com.blazebit.persistence.parser.expression.ParameterExpression)19 ArrayList (java.util.ArrayList)17 ListIndexExpression (com.blazebit.persistence.parser.expression.ListIndexExpression)16 TreatExpression (com.blazebit.persistence.parser.expression.TreatExpression)16 MapValueExpression (com.blazebit.persistence.parser.expression.MapValueExpression)15 GeneralCaseExpression (com.blazebit.persistence.parser.expression.GeneralCaseExpression)11 MapEntryExpression (com.blazebit.persistence.parser.expression.MapEntryExpression)11 QualifiedExpression (com.blazebit.persistence.parser.expression.QualifiedExpression)10 ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)10 EntityType (javax.persistence.metamodel.EntityType)10 PathReference (com.blazebit.persistence.parser.expression.PathReference)8 NullExpression (com.blazebit.persistence.parser.expression.NullExpression)7