diff --git a/core/api/src/main/java/com/blazebit/persistence/spi/JpaProvider.java b/core/api/src/main/java/com/blazebit/persistence/spi/JpaProvider.java index 9a001d9e94..668cb60152 100644 --- a/core/api/src/main/java/com/blazebit/persistence/spi/JpaProvider.java +++ b/core/api/src/main/java/com/blazebit/persistence/spi/JpaProvider.java @@ -107,7 +107,6 @@ public interface JpaProvider { * Whether dereferencing a VALUE function expression is supported by the JPA provider. * * @return True if dereferencing is supported, false otherwise - * @since 1.2.0 */ public boolean supportsCollectionValueDereference(); @@ -156,6 +155,7 @@ public interface JpaProvider { /** * Whether treating a from/root alias is supported. + * For example SELECT TREAT(alias AS Subtype).property FROM .. * * @return True if treating a from alias is supported, false otherwise */ @@ -163,17 +163,35 @@ public interface JpaProvider { /** * Whether a treat join is supported. + * For example SELECT ... FROM .. JOIN TREAT(alias.relation AS Subtype) * * @return True if a treat join is supported, false otherwise */ public boolean supportsTreatJoin(); + /** + * Whether a correlation path with a treat expression is supported. + * For example SELECT (SELECT .. FROM TREAT(parent AS Subtype).relation) FROM .. + * + * @return True if a treat in correlation expressions is supported, false otherwise + */ + public boolean supportsTreatCorrelation(); + + /** + * Whether a root treat in a join is supported. + * For example SELECT ... FROM .. JOIN TREAT(alias AS Subtype).relation + * + * @return True if a root treat in a join is supported, false otherwise + */ + public boolean supportsRootTreatJoin(); + /** * Whether a root treat in a treat join is supported. + * For example SELECT ... FROM .. JOIN TREAT(TREAT(alias AS Subtype).relation AS Subtype) * * @return True if a root treat in a treat join is supported, false otherwise */ - public boolean supportsRootTreatJoin(); + public boolean supportsRootTreatTreatJoin(); /** * Whether properties accessed of a from node are implicitly resolved to properties of a subtype of the from node. @@ -182,6 +200,13 @@ public interface JpaProvider { */ public boolean supportsSubtypePropertyResolving(); + /** + * Whether relations of a from node in joins are implicitly resolved to the relations of a subtype of the from node. + * + * @return True if subtype relation resolving is supported, false otherwise + */ + public boolean supportsSubtypeRelationResolving(); + /** * Whether the COUNT(*) syntax is supported. * @@ -192,11 +217,21 @@ public interface JpaProvider { /** * Whether the join columns for the given attribute are in a foreign table. * - * @param ownerClass The owner of the attribute + * @param ownerType The owner of the attribute * @param attributeName The attribute name to check * @return True if join columns are in a foreign table, false otherwise */ - public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeName); + public boolean isForeignJoinColumn(ManagedType ownerType, String attributeName); + + /** + * Whether columns for the given attribute are shared between multiple subtypes + * or shared by occupying the same slot in the resulting SQL. + * + * @param ownerType The owner of the attribute + * @param attributeName The attribute name to check + * @return True if columns of the attribute are shared, false otherwise + */ + public boolean isColumnShared(ManagedType ownerType, String attributeName); /** * Whether the given attribute is a collection that uses a join table. @@ -235,7 +270,6 @@ public interface JpaProvider { * The value is not yet used but will be in a future version. Also see: https://github.com/Blazebit/blaze-persistence/issues/402 * * @return true if supported, else false - * @since 1.2.0 */ public boolean supportsForeignAssociationInOnClause(); @@ -244,7 +278,6 @@ public interface JpaProvider { * Indicates if the provider supports the use of transient entity objects as parameters. * * @return true if supported, else false - * @since 1.2.0 */ public boolean supportsTransientEntityAsParameter(); @@ -253,8 +286,7 @@ public interface JpaProvider { * If needed, an expression like alias.association in the ON clause is rewritten to * alias.association.id. * - * @return true if supported, else false - * @since 1.2.0 + * @return true if required, else false */ public boolean needsAssociationToIdRewriteInOnClause(); @@ -263,8 +295,16 @@ public interface JpaProvider { * If needed, an expression like alias.association in the ON clause is rewritten to * alias.association.id which relies on a broken type check in older Hibernate versions. * - * @return true if supported, else false - * @since 1.2.0 + * @return true if required, else false */ public boolean needsBrokenAssociationToIdRewriteInOnClause(); + + /** + * Indicates if the provider does column sharing for same named columns in inheritance mappings + * and thus requires the use of a CASE WHEN expression for restricting casted accesses like e.g. TREAT(alias AS Subtype).property + * to retain cast semantics. + * + * @return true if required, else false + */ + public boolean needsTypeConstraintForColumnSharing(); } diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractCommonQueryBuilder.java b/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractCommonQueryBuilder.java index 6b8f95b0df..4c649de121 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractCommonQueryBuilder.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractCommonQueryBuilder.java @@ -687,6 +687,7 @@ public boolean isEmpty() { !fromClassExplicitelySet && joinManager.getRoots().size() == 1 && joinManager.getRoots().get(0).getNodes().isEmpty() + && joinManager.getRoots().get(0).getTreatedJoinNodes().isEmpty() && joinManager.getRoots().get(0).getEntityJoinNodes().isEmpty() ) ; @@ -1570,7 +1571,7 @@ protected List getEntityFunctionNodes(Query baseQuery) { String valuesAliases = node.getValuesAliases(); String valuesTableSqlAlias = cbf.getExtendedQuerySupport().getSqlAlias(em, baseQuery, node.getAlias()); - entityFunctionNodes.add(new EntityFunctionNode(valuesClause, valuesAliases, node.getPropertyClass(), valuesTableSqlAlias, node.getValueQuery())); + entityFunctionNodes.add(new EntityFunctionNode(valuesClause, valuesAliases, node.getType(), valuesTableSqlAlias, node.getValueQuery())); } return entityFunctionNodes; } @@ -1785,7 +1786,7 @@ protected void prepareAndCheck() { joinManager.acceptVisitor(new JoinNodeVisitor() { @Override public void visit(JoinNode node) { - Class cteType = node.getPropertyClass(); + Class cteType = node.getType(); // Except for VALUES clause from nodes, every cte type must be defined if (node.getValueQuery() == null && mainQuery.metamodel.getCte(cteType) != null) { if (mainQuery.cteManager.getCte(cteType) == null) { diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractFullQueryBuilder.java b/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractFullQueryBuilder.java index 94976ac7d9..e17f2a26f7 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractFullQueryBuilder.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/AbstractFullQueryBuilder.java @@ -131,7 +131,7 @@ private void checkEntityId(Object entityId) { throw new IllegalArgumentException("Invalid null entity id given"); } - EntityType entityType = mainQuery.metamodel.entity(joinManager.getRootNodeOrFail("Paginated queries do not support multiple from clause elements!").getPropertyClass()); + EntityType entityType = mainQuery.metamodel.entity(joinManager.getRootNodeOrFail("Paginated queries do not support multiple from clause elements!").getType()); Attribute idAttribute = JpaUtils.getIdAttribute(entityType); Class idType = JpaUtils.resolveFieldClass(entityType.getJavaType(), idAttribute); diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/EntityMetamodelImpl.java b/core/impl/src/main/java/com/blazebit/persistence/impl/EntityMetamodelImpl.java index 9113d5409b..a1fc20e126 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/EntityMetamodelImpl.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/EntityMetamodelImpl.java @@ -23,6 +23,7 @@ import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.BasicType; import javax.persistence.metamodel.EmbeddableType; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; @@ -37,6 +38,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * This is a wrapper around the JPA {@link Metamodel} allows additionally efficient access by other attributes than a Class. @@ -50,7 +53,8 @@ public class EntityMetamodelImpl implements EntityMetamodel { private final Map> entityNameMap; private final Map> entityTypes; private final Map>> enumTypes; - private final Map, ManagedType> classMap; + private final Map, Type> classMap; + private final ConcurrentMap, Type> basicTypeMap = new ConcurrentHashMap<>(); private final Map, ManagedType> cteMap; private final Map, Map>> typeAttributeColumnNameMap; private final Map, Map>> typeAttributeColumnTypeMap; @@ -61,7 +65,7 @@ public EntityMetamodelImpl(EntityManagerFactory emf, ExtendedQuerySupport extend Map> nameToType = new HashMap<>(managedTypes.size()); Map> entityTypes = new HashMap<>(managedTypes.size()); Map>> enumTypes = new HashMap<>(managedTypes.size()); - Map, ManagedType> classToType = new HashMap<>(managedTypes.size()); + Map, Type> classToType = new HashMap<>(managedTypes.size()); Map, ManagedType> cteToType = new HashMap<>(managedTypes.size()); Map, Map>> typeAttributeColumnNames = new HashMap<>(managedTypes.size()); Map, Map>> typeAttributeColumnTypeNames = new HashMap<>(managedTypes.size()); @@ -200,6 +204,14 @@ public EntityType entity(Class cls) { return delegate.entity(cls); } + public EntityType entity(String name) { + EntityType type = entityNameMap.get(name); + if (type == null) { + throw new IllegalArgumentException("Invalid entity type: " + name); + } + return type; + } + @Override public EntityType getEntity(String name) { return entityNameMap.get(name); @@ -223,6 +235,22 @@ public ManagedType managedType(Class cls) { return delegate.managedType(cls); } + @Override + @SuppressWarnings({ "unchecked" }) + public Type type(Class cls) { + Type type = classMap.get(cls); + if (type != null) { + return (Type) type; + } + + type = new BasicTypeImpl<>(cls); + Type oldType = basicTypeMap.putIfAbsent(cls, type); + if (oldType != null) { + type = oldType; + } + return (Type) type; + } + @Override public ManagedType managedType(String name) { ManagedType t = entityNameMap.get(name); @@ -233,15 +261,16 @@ public ManagedType managedType(String name) { return t; } - @SuppressWarnings({ "unchecked" }) @Override + @SuppressWarnings({ "unchecked" }) public ManagedType getManagedType(Class cls) { return (ManagedType) classMap.get(cls); } @Override + @SuppressWarnings({ "unchecked" }) public EntityType getEntity(Class cls) { - ManagedType type = classMap.get(cls); + Type type = classMap.get(cls); if (type == null || !(type instanceof EntityType)) { return null; } @@ -273,4 +302,23 @@ public Set> getEntities() { public Set> getEmbeddables() { return delegate.getEmbeddables(); } + + private static class BasicTypeImpl implements BasicType { + + private final Class cls; + + public BasicTypeImpl(Class cls) { + this.cls = cls; + } + + @Override + public PersistenceType getPersistenceType() { + return PersistenceType.BASIC; + } + + @Override + public Class getJavaType() { + return cls; + } + } } diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/EntitySelectResolveVisitor.java b/core/impl/src/main/java/com/blazebit/persistence/impl/EntitySelectResolveVisitor.java index 967f56342e..be737af1d6 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/EntitySelectResolveVisitor.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/EntitySelectResolveVisitor.java @@ -70,7 +70,7 @@ public void visit(PathExpression expression) { * selects here */ JoinNode baseNode = ((JoinNode) expression.getBaseNode()); - EntityType entityType = m.getEntity(baseNode.getPropertyClass()); + EntityType entityType = m.getEntity(baseNode.getType()); if (entityType == null) { // ignore if the expression is not an entity return; @@ -101,7 +101,7 @@ public int compare(Attribute o1, Attribute o2) { if (resolve) { PathExpression attrPath = new PathExpression(new ArrayList(expression.getExpressions())); - attrPath.setPathReference(new SimplePathReference(baseNode, attr.getName(), null, JpaUtils.resolveFieldClass(entityClass, attr))); + attrPath.setPathReference(new SimplePathReference(baseNode, attr.getName(), JpaUtils.resolveFieldClass(entityClass, attr))); pathExpressions.add(attrPath); } } diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinAliasInfo.java b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinAliasInfo.java index d6b2bdaaf1..eaa12a5d70 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinAliasInfo.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinAliasInfo.java @@ -65,6 +65,10 @@ public String getAbsolutePath() { } } + public void render(StringBuilder sb) { + sb.append(alias); + } + public boolean isImplicit() { return implicit; } diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinManager.java b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinManager.java index d8052a748b..64359c7bc8 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinManager.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinManager.java @@ -65,6 +65,7 @@ import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -138,21 +139,14 @@ void applyFrom(JoinManager joinManager) { private JoinNode applyFrom(JoinNode node) { String rootAlias = node.getAlias(); boolean implicit = node.getAliasInfo().isImplicit(); - Class clazz = node.getPropertyClass(); - String treatFunction = node.getValuesFunction(); - int valueCount = node.getValueCount(); - int attributeCount = node.getAttributeCount(); - Query valuesExampleQuery = node.getValueQuery(); - String valuesClause = node.getValuesClause(); - String valuesAliases = node.getValuesAliases(); JoinAliasInfo rootAliasInfo = new JoinAliasInfo(rootAlias, rootAlias, implicit, true, aliasManager); JoinNode rootNode; if (node.getCorrelationParent() != null) { - throw new IllegalArgumentException("Cloning subqueries not yet implemented!"); + throw new UnsupportedOperationException("Cloning subqueries not yet implemented!"); } else { - rootNode = new JoinNode(rootAliasInfo, clazz, treatFunction, valueCount, attributeCount, valuesExampleQuery, valuesClause, valuesAliases, null); + rootNode = node.cloneRootNode(rootAliasInfo); } rootAliasInfo.setJoinNode(rootNode); @@ -164,6 +158,10 @@ private JoinNode applyFrom(JoinNode node) { applyFrom(rootNode, treeNode); } + if (!node.getTreatedJoinNodes().isEmpty()) { + throw new UnsupportedOperationException("Cloning joins with treat joins is not yet implemented!"); + } + return rootNode; } @@ -180,10 +178,9 @@ private JoinNode applyFrom(JoinNode parent, JoinTreeNode treeNode, String alias, String currentJoinPath = parent.getAliasInfo().getAbsolutePath() + "." + treeNode.getRelationName(); JoinAliasInfo newAliasInfo = new JoinAliasInfo(alias, currentJoinPath, implicit, false, aliasManager); aliasManager.registerAliasInfo(newAliasInfo); - JoinNode node = new JoinNode(parent, treeNode, oldNode.getParentTreatType(), newAliasInfo, oldNode.getJoinType(), oldNode.getPropertyClass(), oldNode.getTreatType(), oldNode.getQualificationExpression()); + JoinNode node = oldNode.cloneJoinNode(parent, treeNode, newAliasInfo); newAliasInfo.setJoinNode(node); - node.setFetch(oldNode.isFetch()); if (oldNode.getOnPredicate() != null) { node.setOnPredicate(subqueryInitFactory.reattachSubqueries(oldNode.getOnPredicate().clone(true))); } @@ -192,6 +189,10 @@ private JoinNode applyFrom(JoinNode parent, JoinTreeNode treeNode, String alias, applyFrom(node, oldTreeNode); } + if (!oldNode.getTreatedJoinNodes().isEmpty()) { + throw new UnsupportedOperationException("Cloning joins with treat joins is not yet implemented!"); + } + return node; } @@ -252,7 +253,7 @@ private void visitKeyOrIndexExpression(PathExpression pathExpression) { } } - String addRootValues(Class clazz, Class valueClazz, String rootAlias, int valueCount, String treatFunction, String castedParameter, boolean identifiableReference) { + String addRootValues(Class clazz, Class valueClazz, String rootAlias, int valueCount, String valuesFunction, String castedParameter, boolean identifiableReference) { if (rootAlias == null) { throw new IllegalArgumentException("Illegal empty alias for the VALUES clause: " + clazz.getName()); } @@ -281,7 +282,7 @@ String addRootValues(Class clazz, Class valueClazz, String rootAlias, int ValueRetriever[] pathExpressions = new ValueRetriever[attributeSet.size()]; StringBuilder valuesSb = new StringBuilder(20 + valueCount * attributeSet.size() * 3); - Query valuesExampleQuery = getValuesExampleQuery(clazz, identifiableReference, rootAlias, treatFunction, castedParameter, attributeSet, parameterNames, pathExpressions, valuesSb, strategy, dummyTable); + Query valuesExampleQuery = getValuesExampleQuery(clazz, identifiableReference, rootAlias, valuesFunction, castedParameter, attributeSet, parameterNames, pathExpressions, valuesSb, strategy, dummyTable); parameterManager.registerValuesParameter(rootAlias, valueClazz, parameterNames, pathExpressions); String exampleQuerySql = mainQuery.cbf.getExtendedQuerySupport().getSql(mainQuery.em, valuesExampleQuery); @@ -317,7 +318,7 @@ String addRootValues(Class clazz, Class valueClazz, String rootAlias, int String valuesClause = valuesSb.toString(); JoinAliasInfo rootAliasInfo = new JoinAliasInfo(rootAlias, rootAlias, true, true, aliasManager); - JoinNode rootNode = new JoinNode(rootAliasInfo, clazz, treatFunction, valueCount, attributeSet.size(), valuesExampleQuery, valuesClause, valuesAliases, null); + JoinNode rootNode = JoinNode.createValuesRootNode(managedType, valuesFunction, valueCount, attributeSet.size(), valuesExampleQuery, valuesClause, valuesAliases, rootAliasInfo); rootAliasInfo.setJoinNode(rootNode); rootNodes.add(rootNode); // register root alias in aliasManager @@ -537,10 +538,10 @@ private Query getValuesExampleQuery(Class clazz, boolean identifiableReferenc return q; } - String addRoot(EntityType clazz, String rootAlias) { + String addRoot(EntityType entityType, String rootAlias) { if (rootAlias == null) { // TODO: not sure if other JPA providers support case sensitive queries like hibernate - StringBuilder sb = new StringBuilder(clazz.getName()); + StringBuilder sb = new StringBuilder(entityType.getName()); sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); String alias = sb.toString(); @@ -551,7 +552,7 @@ String addRoot(EntityType clazz, String rootAlias) { } } JoinAliasInfo rootAliasInfo = new JoinAliasInfo(rootAlias, rootAlias, true, true, aliasManager); - JoinNode rootNode = new JoinNode(null, null, null, rootAliasInfo, null, clazz.getJavaType(), null, null); + JoinNode rootNode = JoinNode.createRootNode(entityType, rootAliasInfo); rootAliasInfo.setJoinNode(rootNode); rootNodes.add(rootNode); // register root alias in aliasManager @@ -560,21 +561,69 @@ String addRoot(EntityType clazz, String rootAlias) { } String addRoot(String correlationPath, String rootAlias) { - // TODO: TREAT support is missing - String[] parts = correlationPath.split("\\."); + Expression expr = expressionFactory.createJoinPathExpression(correlationPath); + + PathElementExpression elementExpr; + EntityType treatEntityType = null; + JoinResult result; + JoinNode correlationParent = null; + if (expr instanceof PathExpression) { + PathExpression pathExpression = (PathExpression) expr; + + if (isJoinableSelectAlias(pathExpression, false, false)) { + throw new IllegalArgumentException("No select alias allowed in join path"); + } + + List pathElements = pathExpression.getExpressions(); + elementExpr = pathElements.get(pathElements.size() - 1); + if (pathElements.size() > 1) { + result = implicitJoin(null, pathExpression, null, 0, pathElements.size() - 1, true); + correlationParent = result.baseNode; + } else { + result = new JoinResult(null, null, null); + } + } else if (expr instanceof TreatExpression) { + TreatExpression treatExpression = (TreatExpression) expr; + Expression expression = treatExpression.getExpression(); + + if (expression instanceof PathExpression) { + PathExpression pathExpression = (PathExpression) expression; + List pathElements = pathExpression.getExpressions(); + elementExpr = pathElements.get(pathElements.size() - 1); + result = implicitJoin(null, pathExpression, null, 0, pathElements.size() - 1, true); + correlationParent = result.baseNode; + treatEntityType = metamodel.entity(treatExpression.getType()); + } else { + throw new IllegalArgumentException("Unexpected expression type[" + expression.getClass().getSimpleName() + "] in treat expression: " + treatExpression); + } + } else { + throw new IllegalArgumentException("Correlation join path [" + correlationPath + "] is not a valid join path"); + } + + if (elementExpr instanceof ArrayExpression) { + throw new IllegalArgumentException("Array expressions are not allowed!"); + } + + if (correlationParent == null) { + correlationParent = getRootNodeOrFail("Could not join correlation path [", correlationPath, "] because it did not use an absolute path but multiple root nodes are available!"); + } + + if (correlationParent.getAliasInfo().getAliasOwner() == aliasManager) { + throw new IllegalArgumentException("The correlation path '" + correlationPath + "' does not seem to be part of a parent query!"); + } - String correlationParentAlias = parts[0]; - String correlationPathWithoutAlias = correlationPath.substring(parts[0].length() + 1); + String correlatedAttribute; + Expression correlatedAttributeExpr; - // We assume that this is a subquery join manager here - AliasInfo aliasInfo = aliasManager.getAliasInfo(correlationParentAlias); - if (aliasInfo == null || !(aliasInfo instanceof JoinAliasInfo) || aliasInfo.getAliasOwner() == aliasManager) { - throw new IllegalArgumentException("No join node for the alias '" + correlationParentAlias + "' could be found in a parent query!"); + if (result.hasField()) { + correlatedAttribute = result.joinFields(elementExpr.toString()); + correlatedAttributeExpr = expressionFactory.createSimpleExpression(correlatedAttribute, false); + } else { + correlatedAttribute = elementExpr.toString(); + correlatedAttributeExpr = elementExpr; } - JoinNode correlationParent = ((JoinAliasInfo) aliasInfo).getJoinNode(); - Expression correlationPathWithoutAliasExpression = expressionFactory.createPathExpression(correlationPathWithoutAlias); - AttributeHolder joinResult = JpaUtils.getAttributeForJoining(metamodel, correlationParent.getPropertyClass(), correlationParent.getParentTreatType(), correlationPathWithoutAliasExpression, null); + AttributeHolder joinResult = JpaUtils.getAttributeForJoining(metamodel, correlationParent.getType(), correlatedAttributeExpr, null); Class attributeType = joinResult.getAttributeJavaType(); if (rootAlias == null) { @@ -588,10 +637,10 @@ String addRoot(String correlationPath, String rootAlias) { rootAlias = aliasManager.generatePostfixedAlias(alias); } } - // TODO: Implement treat support for correlated subqueries - String treatType = null; + + ManagedType managedType = metamodel.managedType(attributeType); JoinAliasInfo rootAliasInfo = new JoinAliasInfo(rootAlias, rootAlias, true, true, aliasManager); - JoinNode rootNode = new JoinNode(correlationParent, correlationPathWithoutAlias, treatType, rootAliasInfo, attributeType, null, null); + JoinNode rootNode = JoinNode.createCorrelationRootNode(correlationParent, correlatedAttribute, managedType, treatEntityType, rootAliasInfo); rootAliasInfo.setJoinNode(rootNode); rootNodes.add(rootNode); // register root alias in aliasManager @@ -661,6 +710,13 @@ boolean hasJoins() { if (!n.getNodes().isEmpty() || !n.getEntityJoinNodes().isEmpty()) { return true; } + if (!n.getTreatedJoinNodes().isEmpty()) { + for (JoinNode treatedNode : n.getTreatedJoinNodes().values()) { + if (!treatedNode.getNodes().isEmpty() || !treatedNode.getEntityJoinNodes().isEmpty()) { + return true; + } + } + } } return false; @@ -686,17 +742,6 @@ Set getEntityFunctionNodes() { return entityFunctionNodes; } - private void fillCollectionJoinsNodesRec(JoinNode node, Set collectionNodes) { - for (JoinTreeNode treeNode : node.getNodes().values()) { - if (treeNode.isCollection()) { - collectionNodes.addAll(treeNode.getJoinNodes().values()); - for (JoinNode childNode : treeNode.getJoinNodes().values()) { - fillCollectionJoinsNodesRec(childNode, collectionNodes); - } - } - } - } - public JoinManager getParent() { return parent; } @@ -724,9 +769,9 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St JoinNode correlationParent = rootNode.getCorrelationParent(); if (externalRepresenation && rootNode.getValueCount() > 0) { - ManagedType type = metamodel.getManagedType(rootNode.getPropertyClass()); + ManagedType type = rootNode.getManagedType(); final int attributeCount = rootNode.getAttributeCount(); - if (rootNode.getPropertyClass() != ValuesEntity.class) { + if (type.getJavaType() != ValuesEntity.class) { if (type instanceof EntityType) { sb.append(((EntityType) type).getName()); } else { @@ -747,9 +792,9 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St } sb.setCharAt(sb.length() - 1, ')'); - } else if (externalRepresenation && explicitVersionEntities.get(rootNode.getPropertyClass()) != null) { - DbmsModificationState state = explicitVersionEntities.get(rootNode.getPropertyClass()).get(rootNode.getAlias()); - EntityType type = metamodel.entity(rootNode.getPropertyClass()); + } else if (externalRepresenation && explicitVersionEntities.get(rootNode.getType()) != null) { + DbmsModificationState state = explicitVersionEntities.get(rootNode.getType()).get(rootNode.getAlias()); + EntityType type = rootNode.getEntityType(); if (state == DbmsModificationState.NEW) { sb.append("NEW("); } else { @@ -759,11 +804,9 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St sb.append(')'); } else { if (correlationParent != null) { - sb.append(correlationParent.getAliasInfo().getAlias()); - sb.append('.'); - sb.append(rootNode.getCorrelationPath()); + renderCorrelationJoinPath(sb, correlationParent.getAliasInfo(), rootNode); } else { - EntityType type = metamodel.entity(rootNode.getPropertyClass()); + EntityType type = rootNode.getEntityType(); sb.append(type.getName()); } } @@ -780,6 +823,9 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St // TODO: not sure if needed since applyImplicitJoins will already invoke that rootNode.registerDependencies(); applyJoins(sb, rootNode.getAliasInfo(), rootNode.getNodes(), clauseExclusions, aliasPrefix, collectCollectionJoinNodes, renderFetches, nodesToFetch); + for (JoinNode treatedNode : rootNode.getTreatedJoinNodes().values()) { + applyJoins(sb, treatedNode.getAliasInfo(), treatedNode.getNodes(), clauseExclusions, aliasPrefix, collectCollectionJoinNodes, renderFetches, nodesToFetch); + } if (!rootNode.getEntityJoinNodes().isEmpty()) { // TODO: Fix this with #216 boolean isCollection = true; @@ -795,7 +841,7 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St sb.append(", "); - EntityType type = metamodel.entity(entityNode.getPropertyClass()); + EntityType type = entityNode.getEntityType(); sb.append(type.getName()); sb.append(' '); @@ -826,6 +872,9 @@ Set buildClause(StringBuilder sb, Set clauseExclusions, St renderedJoins.add(entityNode); applyJoins(sb, entityNode.getAliasInfo(), entityNode.getNodes(), clauseExclusions, aliasPrefix, collectCollectionJoinNodes, renderFetches, nodesToFetch); + for (JoinNode treatedNode : entityNode.getTreatedJoinNodes().values()) { + applyJoins(sb, treatedNode.getAliasInfo(), treatedNode.getNodes(), clauseExclusions, aliasPrefix, collectCollectionJoinNodes, renderFetches, nodesToFetch); + } } } } @@ -878,6 +927,11 @@ private void renderJoinNode(StringBuilder sb, JoinAliasInfo joinBase, JoinNode n renderedJoins.add(node); return; } + // We only render treat joins, but not treated join nodes. These treats are just "optional casts" that don't affect joining + if (node.isTreatedJoinNode()) { + renderedJoins.add(node); + return; + } switch (node.getJoinType()) { case INNER: sb.append(" JOIN "); @@ -900,39 +954,8 @@ private void renderJoinNode(StringBuilder sb, JoinAliasInfo joinBase, JoinNode n sb.append(aliasPrefix); } - if (node.getTreatType() != null) { - if (mainQuery.jpaProvider.supportsTreatJoin()) { - sb.append("TREAT("); - renderParentAlias(sb, node, joinBase.getAlias()); - sb.append(node.getParentTreeNode().getRelationName()); - sb.append(" AS "); - sb.append(node.getTreatType()); - sb.append(") "); - } else if (mainQuery.jpaProvider.supportsSubtypePropertyResolving()) { - sb.append(joinBase.getAlias()).append('.').append(node.getParentTreeNode().getRelationName()).append(' '); - } else { - throw new IllegalArgumentException("Treat should not be used as the JPA provider does not support subtype property access!"); - } - } else if (node.getAliasInfo().isRootNode()) { - sb.append(metamodel.entity(node.getPropertyClass()).getName()).append(' '); - } else if (node.isQualifiedJoin()) { - sb.append(node.getQualificationExpression()); - sb.append('('); - sb.append(joinBase.getJoinNode().getAlias()); - sb.append(')'); - sb.append(' '); - } else { - if (joinBase.getJoinNode().isQualifiedJoin()) { - sb.append(joinBase.getJoinNode().getQualificationExpression()); - sb.append('('); - sb.append(joinBase.getJoinNode().getParent().getAlias()); - sb.append(')'); - sb.append('.'); - } else { - renderParentAlias(sb, node, joinBase.getAlias()); - } - sb.append(node.getParentTreeNode().getRelationName()).append(' '); - } + renderJoinPath(sb, joinBase, node); + sb.append(' '); if (aliasPrefix != null) { sb.append(aliasPrefix); @@ -958,21 +981,78 @@ private void renderJoinNode(StringBuilder sb, JoinAliasInfo joinBase, JoinNode n } } - private void renderParentAlias(StringBuilder sb, JoinNode parentNode, String alias) { - if (parentNode.getParentTreatType() != null) { - if (mainQuery.jpaProvider.supportsRootTreatJoin()) { + private void renderCorrelationJoinPath(StringBuilder sb, JoinAliasInfo joinBase, JoinNode node) { + if (node.getTreatType() != null) { + if (mainQuery.jpaProvider.supportsTreatCorrelation()) { sb.append("TREAT("); - sb.append(alias); + renderAlias(sb, joinBase.getJoinNode(), mainQuery.jpaProvider.supportsRootTreat()); + sb.append('.'); + sb.append(node.getCorrelationPath()); sb.append(" AS "); - sb.append(parentNode.getParentTreatType()); - sb.append(")."); - } else if (mainQuery.jpaProvider.supportsSubtypePropertyResolving()) { - sb.append(alias).append('.'); + sb.append(node.getTreatType().getName()); + sb.append(')'); + } else if (mainQuery.jpaProvider.supportsSubtypeRelationResolving()) { + sb.append(joinBase.getAlias()).append('.').append(node.getCorrelationPath()); } else { throw new IllegalArgumentException("Treat should not be used as the JPA provider does not support subtype property access!"); } } else { - sb.append(alias).append('.'); + JoinNode baseNode = joinBase.getJoinNode(); + if (baseNode.getTreatType() != null) { + if (mainQuery.jpaProvider.supportsRootTreatJoin()) { + baseNode.appendAlias(sb, true); + } else if (mainQuery.jpaProvider.supportsSubtypeRelationResolving()) { + baseNode.appendAlias(sb, false); + } else { + throw new IllegalArgumentException("Treat should not be used as the JPA provider does not support subtype property access!"); + } + } else { + baseNode.appendAlias(sb, false); + } + + sb.append('.').append(node.getCorrelationPath()); + } + } + + private void renderJoinPath(StringBuilder sb, JoinAliasInfo joinBase, JoinNode node) { + if (node.getTreatType() != null) { + if (mainQuery.jpaProvider.supportsTreatJoin()) { + sb.append("TREAT("); + renderAlias(sb, joinBase.getJoinNode(), mainQuery.jpaProvider.supportsRootTreat()); + sb.append('.'); + sb.append(node.getParentTreeNode().getRelationName()); + sb.append(" AS "); + sb.append(node.getTreatType().getName()); + sb.append(')'); + } else if (mainQuery.jpaProvider.supportsSubtypeRelationResolving()) { + sb.append(joinBase.getAlias()).append('.').append(node.getParentTreeNode().getRelationName()); + } else { + throw new IllegalArgumentException("Treat should not be used as the JPA provider does not support subtype property access!"); + } + } else if (node.getCorrelationPath() == null && node.getAliasInfo().isRootNode()) { + sb.append(node.getEntityType().getName()); + } else if (node.isQualifiedJoin()) { + sb.append(node.getQualificationExpression()); + sb.append('('); + sb.append(joinBase.getJoinNode().getAlias()); + sb.append(')'); + } else { + renderAlias(sb, joinBase.getJoinNode(), mainQuery.jpaProvider.supportsRootTreatJoin()); + sb.append('.').append(node.getParentTreeNode().getRelationName()); + } + } + + private void renderAlias(StringBuilder sb, JoinNode baseNode, boolean supportsTreat) { + if (baseNode.getTreatType() != null) { + if (supportsTreat) { + baseNode.appendAlias(sb, true); + } else if (mainQuery.jpaProvider.supportsSubtypeRelationResolving()) { + baseNode.appendAlias(sb, false); + } else { + throw new IllegalArgumentException("Treat should not be used as the JPA provider does not support subtype property access!"); + } + } else { + baseNode.appendAlias(sb, false); } } @@ -1017,6 +1097,7 @@ private void applyJoins(StringBuilder sb, JoinAliasInfo joinBase, List } stack.addAll(node.getEntityJoinNodes()); + stack.addAll(node.getTreatedJoinNodes().values()); // We have to render any dependencies this join node has before actually rendering itself if (!node.getDependencies().isEmpty()) { @@ -1191,7 +1272,7 @@ JoinOnBuilder joinOn(X result, String base, Class clazz, String alias, } JoinAliasInfo joinAliasInfo = new JoinAliasInfo(alias, null, false, true, aliasManager); - JoinNode entityJoinNode = new JoinNode(baseNode, null, null, joinAliasInfo, type, entityType.getJavaType(), null, null); + JoinNode entityJoinNode = JoinNode.createEntityJoinNode(baseNode, type, entityType, joinAliasInfo); joinAliasInfo.setJoinNode(entityJoinNode); baseNode.addEntityJoin(entityJoinNode); aliasManager.registerAliasInfo(joinAliasInfo); @@ -1208,6 +1289,7 @@ JoinOnBuilder joinOn(X result, String path, String alias, JoinType type, JoinNode join(String path, String alias, JoinType type, boolean fetch, boolean defaultJoin) { Expression expr = expressionFactory.createJoinPathExpression(path); PathElementExpression elementExpr; + String treatType = null; JoinResult result; JoinNode current; if (expr instanceof PathExpression) { @@ -1219,7 +1301,7 @@ JoinNode join(String path, String alias, JoinType type, boolean fetch, boolean d List pathElements = pathExpression.getExpressions(); elementExpr = pathElements.get(pathElements.size() - 1); - result = implicitJoin(null, null, pathExpression, null, 0, pathElements.size() - 1); + result = implicitJoin(null, pathExpression, null, 0, pathElements.size() - 1, false); current = result.baseNode; } else if (expr instanceof TreatExpression) { TreatExpression treatExpression = (TreatExpression) expr; @@ -1234,8 +1316,9 @@ JoinNode join(String path, String alias, JoinType type, boolean fetch, boolean d PathExpression pathExpression = (PathExpression) expression; List pathElements = pathExpression.getExpressions(); elementExpr = pathElements.get(pathElements.size() - 1); - result = implicitJoin(null, null, pathExpression, null, 0, pathElements.size() - 1); + result = implicitJoin(null, pathExpression, null, 0, pathElements.size() - 1, false); current = result.baseNode; + treatType = treatExpression.getType(); } else { throw new IllegalArgumentException("Unexpected expression type[" + expression.getClass().getSimpleName() + "] in treat expression: " + treatExpression); } @@ -1245,25 +1328,18 @@ JoinNode join(String path, String alias, JoinType type, boolean fetch, boolean d if (elementExpr instanceof ArrayExpression) { throw new IllegalArgumentException("Array expressions are not allowed!"); + } else if (elementExpr instanceof MapKeyExpression) { + MapKeyExpression mapKeyExpression = (MapKeyExpression) elementExpr; + boolean fromSubquery = false; + boolean fromSelectAlias = false; + boolean joinRequired = true; + current = joinMapKey(mapKeyExpression, alias, null, fromSubquery, fromSelectAlias, joinRequired, fetch, false, defaultJoin); + result = new JoinResult(current, null, current.getType()); } else { - String treatType = null; - if (expr instanceof TreatExpression) { - treatType = ((TreatExpression) expr).getType(); - } - - if (elementExpr instanceof MapKeyExpression) { - MapKeyExpression mapKeyExpression = (MapKeyExpression) elementExpr; - boolean fromSubquery = false; - boolean fromSelectAlias = false; - boolean joinRequired = true; - current = joinMapKey(mapKeyExpression, alias, null, fromSubquery, fromSelectAlias, joinRequired, fetch, false, defaultJoin); - result = new JoinResult(current, null, current.getPropertyClass()); - } else { - List joinRelationAttributes = result.addToList(new ArrayList()); - joinRelationAttributes.add(elementExpr.toString()); - current = current == null ? getRootNodeOrFail("Could not join path [", path, "] because it did not use an absolute path but multiple root nodes are available!") : current; - result = createOrUpdateNode(current, result.typeName, joinRelationAttributes, treatType, alias, type, false, defaultJoin); - } + List joinRelationAttributes = result.addToList(new ArrayList()); + joinRelationAttributes.add(elementExpr.toString()); + current = current == null ? getRootNodeOrFail("Could not join path [", path, "] because it did not use an absolute path but multiple root nodes are available!") : current; + result = createOrUpdateNode(current, joinRelationAttributes, treatType, alias, type, false, defaultJoin); } if (fetch) { @@ -1312,7 +1388,6 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin PathElementExpression elementExpr = pathElements.get(pathElements.size() - 1); boolean singleValuedAssociationIdExpression = false; JoinNode current = null; - String currentTreatType = null; List resultFields = new ArrayList(); JoinResult currentResult; @@ -1328,9 +1403,8 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (pathElements.size() > startIndex + 1) { int maybeSingularAssociationIndex = pathElements.size() - 2; int maybeSingularAssociationIdIndex = pathElements.size() - 1; - currentResult = implicitJoin(current, currentTreatType, pathExpression, fromClause, startIndex, maybeSingularAssociationIndex); + currentResult = implicitJoin(current, pathExpression, fromClause, startIndex, maybeSingularAssociationIndex, false); current = currentResult.baseNode; - currentTreatType = currentResult.typeName; resultFields = currentResult.addToList(resultFields); singleValuedAssociationIdExpression = isSingleValuedAssociationId(currentResult, pathElements, idRemovable); @@ -1346,14 +1420,12 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin AliasInfo a = aliasManager.getAliasInfo(pathElements.get(maybeSingularAssociationIndex).toString()); // We know this can only be a join node alias current = ((JoinAliasInfo) a).getJoinNode(); - currentTreatType = null; resultFields = Collections.emptyList(); } } else { // Need a normal join - currentResult = implicitJoin(current, currentTreatType, pathExpression, fromClause, maybeSingularAssociationIndex, pathElements.size() - 1); + currentResult = implicitJoin(current, pathExpression, fromClause, maybeSingularAssociationIndex, pathElements.size() - 1, false); current = currentResult.baseNode; - currentTreatType = currentResult.typeName; resultFields = currentResult.addToList(resultFields); singleValuedAssociationIdExpression = false; } @@ -1362,29 +1434,27 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (currentResult.hasField()) { // currentResult.typeName? // Redo the joins for embeddables by moving the start index back - currentResult = implicitJoin(current, currentTreatType, pathExpression, fromClause, maybeSingularAssociationIndex - currentResult.fields.size(), maybeSingularAssociationIdIndex); + currentResult = implicitJoin(current, pathExpression, fromClause, maybeSingularAssociationIndex - currentResult.fields.size(), maybeSingularAssociationIdIndex, false); if (currentResult.fields != resultFields) { resultFields.clear(); } } else { - currentResult = implicitJoin(current, currentTreatType, pathExpression, fromClause, maybeSingularAssociationIndex, maybeSingularAssociationIdIndex); + currentResult = implicitJoin(current, pathExpression, fromClause, maybeSingularAssociationIndex, maybeSingularAssociationIdIndex, false); } current = currentResult.baseNode; - currentTreatType = currentResult.typeName; resultFields = currentResult.addToList(resultFields); } } else { // Single element expression like "alias", "relation", "property" or "alias.relation" - currentResult = implicitJoin(current, currentTreatType, pathExpression, fromClause, startIndex, pathElements.size() - 1); + currentResult = implicitJoin(current, pathExpression, fromClause, startIndex, pathElements.size() - 1, false); current = currentResult.baseNode; - currentTreatType = currentResult.typeName; resultFields = currentResult.addToList(resultFields); if (idRemovable) { if (current != null) { // If there is a "base node" i.e. a current, the expression has 2 elements - if (isId(current.getPropertyClass(), elementExpr)) { + if (isId(current.getType(), elementExpr)) { // We remove the "id" part elementExpr = null; // Treat it like a single valued association id expression @@ -1403,7 +1473,7 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (a == null) { // If the element expression is an alias, there is nothing to replace current = getRootNodeOrFail("Could not join path [", expression, "] because it did not use an absolute path but multiple root nodes are available!"); - if (isId(current.getPropertyClass(), elementExpr)) { + if (isId(current.getType(), elementExpr)) { // We replace the "id" part with the alias elementExpr = new PropertyExpression(current.getAlias()); } @@ -1444,10 +1514,10 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (targetTypeName != null) { // Treated root path ManagedType targetType = metamodel.managedType(targetTypeName); - result = new JoinResult(pathJoinNode, null, targetTypeName, targetType.getJavaType()); + result = new JoinResult(pathJoinNode, null, targetType.getJavaType()); } else { // Naked join alias usage like in "KEY(joinAlias)" - result = new JoinResult(pathJoinNode, null, pathJoinNode.getPropertyClass()); + result = new JoinResult(pathJoinNode, null, pathJoinNode.getType()); } } } else if (pathElements.size() == 1 && elementExpr instanceof QualifiedExpression) { @@ -1466,7 +1536,7 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin throw new IllegalArgumentException("Unknown qualified expression type: " + elementExpr); } - result = new JoinResult(baseNode, null, baseNode.getPropertyClass()); + result = new JoinResult(baseNode, null, baseNode.getType()); } else { // current might be null if (current == null) { @@ -1489,15 +1559,14 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (elementExpr != null) { AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining( metamodel, - singleValuedAssociationRoot.getPropertyClass(), - singleValuedAssociationRoot.getTreatType(), + singleValuedAssociationRoot.getType(), elementExpr, singleValuedAssociationRoot.getAlias() ); Class type = attributeHolder.getAttributeJavaType(); result = new JoinResult(singleValuedAssociationRoot, Arrays.asList(elementExpr.toString()), type); } else { - result = new JoinResult(singleValuedAssociationRoot, null, singleValuedAssociationRoot.getPropertyClass()); + result = new JoinResult(singleValuedAssociationRoot, null, singleValuedAssociationRoot.getType()); } } else { treeNode = current.getNodes().get(associationName); @@ -1506,15 +1575,14 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin if (elementExpr != null) { AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining( metamodel, - treeNode.getDefaultNode().getPropertyClass(), - treeNode.getDefaultNode().getTreatType(), + treeNode.getDefaultNode().getType(), elementExpr, treeNode.getDefaultNode().getAlias() ); Class type = attributeHolder.getAttributeJavaType(); result = new JoinResult(treeNode.getDefaultNode(), Arrays.asList(elementExpr.toString()), type); } else { - result = new JoinResult(treeNode.getDefaultNode(), null, treeNode.getDefaultNode().getPropertyClass()); + result = new JoinResult(treeNode.getDefaultNode(), null, treeNode.getDefaultNode().getType()); } } else { if (elementExpr != null) { @@ -1522,8 +1590,7 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin Expression resultExpr = expressionFactory.createSimpleExpression(associationName + '.' + elementString, false); AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining( metamodel, - current.getPropertyClass(), - current.getTreatType(), + current.getType(), resultExpr, current.getAlias() ); @@ -1533,8 +1600,7 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin Expression resultExpr = expressionFactory.createSimpleExpression(associationName, false); AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining( metamodel, - current.getPropertyClass(), - current.getTreatType(), + current.getType(), resultExpr, current.getAlias() ); @@ -1568,7 +1634,7 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin current = matchingNode; } else { String joinAlias = getJoinAlias(arrayExpr); - currentResult = createOrUpdateNode(current, currentTreatType, Arrays.asList(joinRelationName), null, joinAlias, null, true, false); + currentResult = createOrUpdateNode(current, Arrays.asList(joinRelationName), null, joinAlias, null, true, false); current = currentResult.baseNode; // TODO: Not sure if necessary if (currentResult.hasField()) { @@ -1578,29 +1644,29 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin generateAndApplyOnPredicate(current, arrayExpr); } - result = new JoinResult(current, null, current.getPropertyClass()); + result = new JoinResult(current, null, current.getType()); } else if (!pathExpression.isUsedInCollectionFunction()) { if (resultFields.isEmpty()) { - result = implicitJoinSingle(current, currentTreatType, elementExpr.toString(), objectLeafAllowed, joinRequired); + result = implicitJoinSingle(current, elementExpr.toString(), objectLeafAllowed, joinRequired); } else { resultFields.add(elementExpr.toString()); String attributeName = StringUtils.join(".", resultFields); // Validates and gets the path type - getPathType(current.getPropertyClass(), currentTreatType, attributeName, pathExpression); + getPathType(current.getType(), attributeName, pathExpression); - result = implicitJoinSingle(current, currentTreatType, attributeName, objectLeafAllowed, joinRequired); + result = implicitJoinSingle(current, attributeName, objectLeafAllowed, joinRequired); } } else { if (resultFields.isEmpty()) { String attributeName = elementExpr.toString(); - Class type = getPathType(current.getPropertyClass(), currentTreatType, attributeName, pathExpression); + Class type = getPathType(current.getType(), attributeName, pathExpression); result = new JoinResult(current, Arrays.asList(attributeName), type); } else { resultFields.add(elementExpr.toString()); String attributeName = StringUtils.join(".", resultFields); - Class type = getPathType(current.getPropertyClass(), currentTreatType, attributeName, pathExpression); + Class type = getPathType(current.getType(), attributeName, pathExpression); result = new JoinResult(current, resultFields, type); } @@ -1617,13 +1683,9 @@ public void implicitJoin(Expression expression, boolean objectLeafAllowed, Strin } if (result.isLazy()) { - pathExpression.setPathReference(new LazyPathReference(result.baseNode, result.joinFields(), result.typeName, result.type)); + pathExpression.setPathReference(new LazyPathReference(result.baseNode, result.joinFields(), result.type)); } else { - pathExpression.setPathReference(new SimplePathReference(result.baseNode, result.joinFields(), result.typeName, result.type)); - } - - if (result.hasTreatedSubpath) { - pathExpression.setHasTreatedSubpath(true); + pathExpression.setPathReference(new SimplePathReference(result.baseNode, result.joinFields(), result.type)); } } else if (expression instanceof FunctionExpression) { List expressions = ((FunctionExpression) expression).getExpressions(); @@ -1655,13 +1717,11 @@ private JoinNode getFetchOwner(JoinNode node) { private static class LazyPathReference implements PathReference { private final JoinNode baseNode; private final String field; - private final String typeName; private final Class type; - public LazyPathReference(JoinNode baseNode, String field, String typeName, Class type) { + public LazyPathReference(JoinNode baseNode, String field, Class type) { this.baseNode = baseNode; this.field = field; - this.typeName = typeName; this.type = type; } @@ -1685,11 +1745,6 @@ public String getField() { return field; } - @Override - public String getTreatTypeName() { - return typeName; - } - @Override public Class getType() { return type; @@ -1701,7 +1756,6 @@ public int hashCode() { int result = 1; result = prime * result + ((baseNode == null) ? 0 : baseNode.hashCode()); result = prime * result + ((field == null) ? 0 : field.hashCode()); - result = prime * result + ((typeName == null) ? 0 : typeName.hashCode()); return result; } @@ -1731,20 +1785,13 @@ public boolean equals(Object obj) { } else if (!field.equals(other.getField())) { return false; } - if (typeName == null) { - if (other.getTreatTypeName() != null) { - return false; - } - } else if (!typeName.equals(other.getTreatTypeName())) { - return false; - } return true; } } - private Class getPathType(Class baseType, String treatTypeName, String expression, PathExpression pathExpression) { + private Class getPathType(Class baseType, String expression, PathExpression pathExpression) { try { - return JpaUtils.getAttributeForJoining(metamodel, baseType, treatTypeName, expressionFactory.createPathExpression(expression), null).getAttributeJavaType(); + return JpaUtils.getAttributeForJoining(metamodel, baseType, expressionFactory.createPathExpression(expression), null).getAttributeJavaType(); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException("The join path [" + pathExpression + "] has a non joinable part [" + expression + "]"); @@ -1753,50 +1800,52 @@ private Class getPathType(Class baseType, String treatTypeName, String exp private boolean isSingleValuedAssociationId(JoinResult joinResult, List pathElements, boolean idRemovable) { JoinNode parent = joinResult.baseNode; - String parentTypeName = joinResult.typeName; int maybeSingularAssociationIndex = pathElements.size() - 2; int maybeSingularAssociationIdIndex = pathElements.size() - 1; - ManagedType baseType; + Type baseType; AttributeHolder maybeSingularAssociationJoinResult; PathElementExpression maybeSingularAssociationNameExpression = pathElements.get(maybeSingularAssociationIndex); String maybeSingularAssociationName = getSimpleName(maybeSingularAssociationNameExpression); if (parent == null) { // This is the case when we have exactly 2 path elements - AliasInfo a = aliasManager.getAliasInfo(maybeSingularAssociationName); - - if (a == null) { - // if the path element is no alias we can do some optimizations - parent = getRootNodeOrFail("Ambiguous join path [", maybeSingularAssociationName, "] because of multiple root nodes!"); - baseType = metamodel.managedType(parent.getPropertyClass()); - maybeSingularAssociationJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseType.getJavaType(), joinResult.typeName, maybeSingularAssociationNameExpression, parent.getAlias()); - } else if (!(a instanceof JoinAliasInfo)) { - throw new IllegalArgumentException("Can't dereference select alias in the expression!"); + if (maybeSingularAssociationNameExpression instanceof TreatExpression) { + // When we dereference a treat expression, we simply say this can never be a single valued association id + return false; } else { - // If there is a JoinAliasInfo for the path element, we have to use the alias - // We can only "consider" this path a single valued association id when we are about to "remove" the id part - if (idRemovable) { - Class maybeSingularAssociationClass = ((JoinAliasInfo) a).getJoinNode().getPropertyClass(); - PathElementExpression maybeSingularAssociationIdExpression = pathElements.get(maybeSingularAssociationIdIndex); - - return isId(maybeSingularAssociationClass, maybeSingularAssociationIdExpression); + AliasInfo a = aliasManager.getAliasInfo(maybeSingularAssociationName); + + if (a == null) { + // if the path element is no alias we can do some optimizations + parent = getRootNodeOrFail("Ambiguous join path [", maybeSingularAssociationName, "] because of multiple root nodes!"); + baseType = parent.getManagedType(); + maybeSingularAssociationJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseType.getJavaType(), maybeSingularAssociationNameExpression, parent.getAlias()); + } else if (!(a instanceof JoinAliasInfo)) { + throw new IllegalArgumentException("Can't dereference select alias in the expression!"); } else { - // Otherwise we return false in order to signal that a normal implicit join should be done - return false; + // If there is a JoinAliasInfo for the path element, we have to use the alias + // We can only "consider" this path a single valued association id when we are about to "remove" the id part + if (idRemovable) { + Class maybeSingularAssociationClass = ((JoinAliasInfo) a).getJoinNode().getType(); + PathElementExpression maybeSingularAssociationIdExpression = pathElements.get(maybeSingularAssociationIdIndex); + + return isId(maybeSingularAssociationClass, maybeSingularAssociationIdExpression); + } else { + // Otherwise we return false in order to signal that a normal implicit join should be done + return false; + } } } } else { - Class parentClass = parent.getPropertyClass(); - if (joinResult.hasField()) { Expression fieldExpression = expressionFactory.createPathExpression(joinResult.joinFields()); - AttributeHolder result = JpaUtils.getAttributeForJoining(metamodel, parentClass, parentTypeName, fieldExpression, parent.getAlias()); - baseType = metamodel.getManagedType(result.getAttributeJavaType()); + AttributeHolder result = JpaUtils.getAttributeForJoining(metamodel, parent.getType(), fieldExpression, parent.getAlias()); + baseType = metamodel.type(result.getAttributeJavaType()); } else { - baseType = JpaUtils.getManagedType(metamodel, parentClass, parentTypeName); + baseType = parent.getNodeType(); } - maybeSingularAssociationJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseType.getJavaType(), null, maybeSingularAssociationNameExpression, null); + maybeSingularAssociationJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseType.getJavaType(), maybeSingularAssociationNameExpression, null); } Attribute maybeSingularAssociation = maybeSingularAssociationJoinResult.getAttribute(); @@ -1817,12 +1866,12 @@ private boolean isSingleValuedAssociationId(JoinResult joinResult, List) { // Get the base type. This is important if the path is "deeper" i.e. when having embeddables - baseType = JpaUtils.getManagedType(metamodel, parent.getPropertyClass(), parentTypeName); + baseType = parent.getNodeType(); String attributePath = joinResult.joinFields(maybeSingularAssociationName); - if (mainQuery.jpaProvider.isForeignJoinColumn(baseType, attributePath)) { + if (mainQuery.jpaProvider.isForeignJoinColumn((ManagedType) baseType, attributePath)) { return false; } - } else if (mainQuery.jpaProvider.isForeignJoinColumn(baseType, maybeSingularAssociation.getName())) { + } else if (mainQuery.jpaProvider.isForeignJoinColumn((ManagedType) baseType, maybeSingularAssociation.getName())) { return false; } @@ -1890,7 +1939,7 @@ private String getJoinAlias(ArrayExpression expr) { private EqPredicate getArrayExpressionPredicate(JoinNode joinNode, ArrayExpression arrayExpr) { PathExpression keyPath = new PathExpression(new ArrayList(), true); keyPath.getExpressions().add(new PropertyExpression(joinNode.getAliasInfo().getAlias())); - keyPath.setPathReference(new SimplePathReference(joinNode, null, null, joinNode.getPropertyClass())); + keyPath.setPathReference(new SimplePathReference(joinNode, null, joinNode.getType())); Attribute arrayBaseAttribute = joinNode.getParentTreeNode().getAttribute(); Expression keyExpression; if (arrayBaseAttribute instanceof ListAttribute) { @@ -1934,10 +1983,9 @@ private void generateAndApplyOnPredicate(JoinNode joinNode, ArrayExpression arra } } - private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathExpression pathExpression, ClauseType fromClause, int start, int end) { + private JoinResult implicitJoin(JoinNode current, PathExpression pathExpression, ClauseType fromClause, int start, int end, boolean allowParentAliases) { List pathElements = pathExpression.getExpressions(); List resultFields = new ArrayList(); - String currentTargetType = currentTreatType; PathElementExpression elementExpr; for (int i = start; i < end; i++) { @@ -1974,14 +2022,11 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE generateAndApplyOnPredicate(current, arrayExpr); } else { String joinAlias = getJoinAlias(arrayExpr); - final JoinResult result = createOrUpdateNode(current, currentTargetType, joinRelationAttributes, null, joinAlias, null, true, false); + final JoinResult result = createOrUpdateNode(current, joinRelationAttributes, null, joinAlias, null, true, false); current = result.baseNode; resultFields = result.addToList(resultFields); generateAndApplyOnPredicate(current, arrayExpr); } - - // Reset target type - currentTargetType = null; } else if (elementExpr instanceof TreatExpression) { if (i != 0 || current != null) { throw new IllegalArgumentException("A treat expression should be the first element in a path!"); @@ -1992,14 +2037,12 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE boolean joinRequired = false; boolean fetch = false; - // TODO: reuse existing treated join node or create one? not sure if it wasn't better to just pass it through to the persistence provider if (treatExpression.getExpression() instanceof PathExpression) { PathExpression treatedPathExpression = (PathExpression) treatExpression.getExpression(); implicitJoin(treatedPathExpression, true, treatExpression.getType(), fromClause, fromSubquery, fromSelectAlias, true, false, fetch); JoinNode treatedJoinNode = (JoinNode) treatedPathExpression.getBaseNode(); - current = treatedJoinNode; - // TODO: check if the types are actually assignable - currentTargetType = treatExpression.getType(); + EntityType treatType = metamodel.getEntity(treatExpression.getType()); + current = treatedJoinNode.getTreatedJoinNode(treatType); } else { throw new UnsupportedOperationException("Unsupported treated expression type: " + treatExpression.getExpression().getClass()); } @@ -2010,8 +2053,6 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE boolean joinRequired = true; boolean fetch = false; current = joinMapKey(mapKeyExpression, null, fromClause, fromSubquery, fromSelectAlias, joinRequired, fetch, true, true); - // Reset target type - currentTargetType = null; } else if (elementExpr instanceof MapValueExpression) { MapValueExpression mapValueExpression = (MapValueExpression) elementExpr; boolean fromSubquery = false; @@ -2021,8 +2062,6 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE implicitJoin(mapValueExpression.getPath(), true, null, fromClause, fromSubquery, fromSelectAlias, joinRequired, fetch); current = (JoinNode) mapValueExpression.getPath().getBaseNode(); - // Reset target type - currentTargetType = null; } else if (pathElements.size() == 1 && (aliasInfo = aliasManager.getAliasInfoForBottomLevel(elementExpr.toString())) != null) { if (aliasInfo instanceof SelectInfo) { throw new IllegalArgumentException("Can't dereference a select alias"); @@ -2030,24 +2069,18 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE // Join alias usage like in "joinAlias.relationName" current = ((JoinAliasInfo) aliasInfo).getJoinNode(); } - // Reset target type - currentTargetType = null; } else { if (!resultFields.isEmpty()) { resultFields.add(elementExpr.toString()); - JoinResult currentResult = createOrUpdateNode(current, currentTargetType, resultFields, null, null, null, true, true); + JoinResult currentResult = createOrUpdateNode(current, resultFields, null, null, null, true, true); current = currentResult.baseNode; if (!currentResult.hasField()) { resultFields.clear(); } - // Reset target type - currentTargetType = null; } else { - final JoinResult result = implicitJoinSingle(current, currentTargetType, elementExpr.toString()); + final JoinResult result = implicitJoinSingle(current, elementExpr.toString(), allowParentAliases); if (current != result.baseNode) { current = result.baseNode; - // Reset target type - currentTargetType = null; } resultFields = result.addToList(resultFields); } @@ -2056,7 +2089,7 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE } if (resultFields.isEmpty()) { - return new JoinResult(current, null, currentTargetType, current == null ? null : current.getPropertyClass()); + return new JoinResult(current, null, current == null ? null : current.getType()); } else { StringBuilder sb = new StringBuilder(); sb.append(resultFields.get(0)); @@ -2065,8 +2098,8 @@ private JoinResult implicitJoin(JoinNode current, String currentTreatType, PathE sb.append(resultFields.get(i)); } Expression expression = expressionFactory.createSimpleExpression(sb.toString(), false); - Class type = JpaUtils.getAttributeForJoining(metamodel, current.getPropertyClass(), currentTargetType, expression, current.getAlias()).getAttributeJavaType(); - return new JoinResult(current, resultFields, currentTargetType, type); + Class type = JpaUtils.getAttributeForJoining(metamodel, current.getType(), expression, current.getAlias()).getAttributeJavaType(); + return new JoinResult(current, resultFields, type); } } @@ -2075,10 +2108,10 @@ private JoinNode joinMapKey(MapKeyExpression mapKeyExpression, String alias, Cla JoinNode current = (JoinNode) mapKeyExpression.getPath().getBaseNode(); String joinRelationName = "KEY(" + current.getParentTreeNode().getRelationName() + ")"; MapAttribute mapAttribute = (MapAttribute) current.getParentTreeNode().getAttribute(); - Class keyType = mapAttribute.getKeyJavaType(); Attribute keyAttribute = new MapKeyAttribute<>(mapAttribute); String aliasToUse = alias == null ? current.getParentTreeNode().getRelationName() + "_key" : alias; - current = getOrCreate(current, null, joinRelationName, keyType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, keyAttribute); + Type joinRelationType = metamodel.type(mapAttribute.getKeyJavaType()); + current = getOrCreate(current, joinRelationName, joinRelationType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, keyAttribute); return current; } @@ -2087,10 +2120,10 @@ private JoinNode joinMapEntry(MapEntryExpression mapEntryExpression, String alia JoinNode current = (JoinNode) mapEntryExpression.getPath().getBaseNode(); String joinRelationName = "ENTRY(" + current.getParentTreeNode().getRelationName() + ")"; MapAttribute mapAttribute = (MapAttribute) current.getParentTreeNode().getAttribute(); - Class keyType = mapAttribute.getKeyJavaType(); Attribute entryAttribute = new MapEntryAttribute<>(mapAttribute); - String aliasToUse = alias == null ? current.getParentTreeNode().getRelationName() + "_key" : alias; - current = getOrCreate(current, null, joinRelationName, keyType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, entryAttribute); + String aliasToUse = alias == null ? current.getParentTreeNode().getRelationName() + "_entry" : alias; + Type joinRelationType = metamodel.type(Map.Entry.class); + current = getOrCreate(current, joinRelationName, joinRelationType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, entryAttribute); return current; } @@ -2099,21 +2132,23 @@ private JoinNode joinListIndex(ListIndexExpression listIndexExpression, String a JoinNode current = (JoinNode) listIndexExpression.getPath().getBaseNode(); String joinRelationName = "INDEX(" + current.getParentTreeNode().getRelationName() + ")"; ListAttribute listAttribute = (ListAttribute) current.getParentTreeNode().getAttribute(); - Class keyType = Integer.class; Attribute indexAttribute = new ListIndexAttribute<>(listAttribute); String aliasToUse = alias == null ? current.getParentTreeNode().getRelationName() + "_index" : alias; - current = getOrCreate(current, null, joinRelationName, keyType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, indexAttribute); + Type joinRelationType = metamodel.type(Integer.class); + current = getOrCreate(current, joinRelationName, joinRelationType, null, aliasToUse, JoinType.LEFT, "Ambiguous implicit join", implicit, true, indexAttribute); return current; } - private JoinResult implicitJoinSingle(JoinNode baseNode, String baseNodeTreatType, String attributeName) { + private JoinResult implicitJoinSingle(JoinNode baseNode, String attributeName, boolean allowParentAliases) { if (baseNode == null) { // When no base is given, check if the attribute name is an alias - AliasInfo aliasInfo = aliasManager.getAliasInfoForBottomLevel(attributeName); + AliasInfo aliasInfo = allowParentAliases ? + aliasManager.getAliasInfo(attributeName) : + aliasManager.getAliasInfoForBottomLevel(attributeName); if (aliasInfo != null && aliasInfo instanceof JoinAliasInfo) { JoinNode node = ((JoinAliasInfo) aliasInfo).getJoinNode(); // if it is, we can just return the join node - return new JoinResult(node, null, node.getPropertyClass()); + return new JoinResult(node, null, node.getType()); } } @@ -2123,48 +2158,32 @@ private JoinResult implicitJoinSingle(JoinNode baseNode, String baseNodeTreatTyp } // check if the path is joinable, assuming it is relative to the root (implicit root prefix) - return createOrUpdateNode(baseNode, baseNodeTreatType, Arrays.asList(attributeName), null, null, null, true, true); + return createOrUpdateNode(baseNode, Arrays.asList(attributeName), null, null, null, true, true); } - private JoinResult implicitJoinSingle(JoinNode baseNode, String treatTypeName, String attributeName, boolean objectLeafAllowed, boolean joinRequired) { + private JoinResult implicitJoinSingle(JoinNode baseNode, String attributeName, boolean objectLeafAllowed, boolean joinRequired) { JoinNode newBaseNode; String field; Class type; - boolean hasTreatedSubpath = false; boolean lazy = false; // The given path may be relative to the root or it might be an alias if (objectLeafAllowed) { - String typeName; - ManagedType baseNodeType; - - if (treatTypeName != null) { - typeName = treatTypeName; - baseNodeType = metamodel.managedType(treatTypeName); - } else { - if (baseNode.getTreatType() != null) { - typeName = baseNode.getTreatType(); - baseNodeType = metamodel.managedType(baseNode.getTreatType()); - } else { - typeName = baseNode.getPropertyClass().getSimpleName(); - baseNodeType = metamodel.managedType(baseNode.getPropertyClass()); - } - } + Type baseNodeType = baseNode.getNodeType(); AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining(metamodel, baseNodeType.getJavaType(), expressionFactory.createJoinPathExpression(attributeName), baseNode.getAlias()); Attribute attr = attributeHolder.getAttribute(); if (attr == null) { - throw new IllegalArgumentException("Field with name '" + attributeName + "' was not found within managed type " + typeName); + throw new IllegalArgumentException("Field with name '" + attributeName + "' was not found within managed type " + baseNodeType.getJavaType().getName()); } if (joinRequired || attr.isCollection()) { - final JoinResult newBaseNodeResult = implicitJoinSingle(baseNode, treatTypeName, attributeName); + final JoinResult newBaseNodeResult = implicitJoinSingle(baseNode, attributeName, false); newBaseNode = newBaseNodeResult.baseNode; // check if the last path element was also joined if (newBaseNode != baseNode) { field = null; - type = newBaseNode.getPropertyClass(); + type = newBaseNode.getType(); } else { - hasTreatedSubpath = treatTypeName != null; field = attributeName; type = attributeHolder.getAttributeJavaType(); } @@ -2173,10 +2192,9 @@ private JoinResult implicitJoinSingle(JoinNode baseNode, String treatTypeName, S field = attributeName; type = attributeHolder.getAttributeJavaType(); lazy = true; - hasTreatedSubpath = treatTypeName != null; } } else { - Class baseNodeType = baseNode.getPropertyClass(); + Class baseNodeType = baseNode.getType(); AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining(metamodel, baseNodeType, expressionFactory.createJoinPathExpression(attributeName), baseNode.getAlias()); Attribute attr = attributeHolder.getAttribute(); if (attr == null) { @@ -2189,7 +2207,7 @@ private JoinResult implicitJoinSingle(JoinNode baseNode, String treatTypeName, S field = attributeName; type = attr.getJavaType(); } - return new JoinResult(newBaseNode, field == null ? null : Arrays.asList(field), type, lazy, hasTreatedSubpath); + return new JoinResult(newBaseNode, field == null ? null : Arrays.asList(field), type, lazy); } private void updateClauseDependencies(JoinNode baseNode, ClauseType clauseDependency, Set seenNodes) { @@ -2223,15 +2241,8 @@ private JoinType getModelAwareType(JoinNode baseNode, Attribute attr) { } } - private JoinResult createOrUpdateNode(JoinNode baseNode, String baseNodeTreatType, List joinRelationAttributes, String treatType, String alias, JoinType joinType, boolean implicit, boolean defaultJoin) { - Class baseNodeType; - if (baseNodeTreatType != null) { - baseNodeType = metamodel.getEntity(baseNodeTreatType).getJavaType(); - } else if (baseNode.getTreatType() != null) { - baseNodeType = metamodel.getEntity(baseNode.getTreatType()).getJavaType(); - } else { - baseNodeType = baseNode.getPropertyClass(); - } + private JoinResult createOrUpdateNode(JoinNode baseNode, List joinRelationAttributes, String treatType, String alias, JoinType joinType, boolean implicit, boolean defaultJoin) { + Class baseNodeType = baseNode.getType(); String joinRelationName = StringUtils.join(".", joinRelationAttributes); AttributeHolder attrJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseNodeType, expressionFactory.createJoinPathExpression(joinRelationName), baseNode.getAlias()); Attribute attr = attrJoinResult.getAttribute(); @@ -2259,18 +2270,10 @@ private JoinResult createOrUpdateNode(JoinNode baseNode, String baseNodeTreatTyp joinType = getModelAwareType(baseNode, attr); } - if (baseNodeTreatType != null) { - // Verify it's a valid type - metamodel.managedType(baseNodeTreatType).getJavaType(); - } - if (treatType != null) { - // Verify it's a valid type - metamodel.managedType(treatType).getJavaType(); - } + Type joinRelationType = metamodel.type(attrJoinResult.getAttributeJavaType()); + JoinNode newNode = getOrCreate(baseNode, joinRelationName, joinRelationType, treatType, alias, joinType, "Ambiguous implicit join", implicit, defaultJoin, attr); - JoinNode newNode = getOrCreate(baseNode, baseNodeTreatType, joinRelationName, attrJoinResult.getAttributeJavaType(), treatType, alias, joinType, "Ambiguous implicit join", implicit, defaultJoin, attr); - - return new JoinResult(newNode, null, newNode.getPropertyClass()); + return new JoinResult(newNode, null, newNode.getType()); } private void checkAliasIsAvailable(String alias, String currentJoinPath, String errorMessage) { @@ -2289,7 +2292,7 @@ private void checkAliasIsAvailable(String alias, String currentJoinPath, String } } - private JoinNode getOrCreate(JoinNode baseNode, String baseNodeTreatType, String joinRelationName, Class joinRelationClass, String treatType, String alias, JoinType type, String errorMessage, boolean implicit, boolean defaultJoin, Attribute attribute) { + private JoinNode getOrCreate(JoinNode baseNode, String joinRelationName, Type joinRelationType, String treatType, String alias, JoinType type, String errorMessage, boolean implicit, boolean defaultJoin, Attribute attribute) { JoinTreeNode treeNode = baseNode.getOrCreateTreeNode(joinRelationName, attribute); JoinNode node = treeNode.getJoinNode(alias, defaultJoin); String qualificationExpression = null; @@ -2298,7 +2301,18 @@ private JoinNode getOrCreate(JoinNode baseNode, String baseNodeTreatType, String qualificationExpression = ((QualifiedAttribute) attribute).getQualificationExpression(); } - String currentJoinPath = baseNode.getAliasInfo().getAbsolutePath() + "." + joinRelationName; + EntityType treatJoinType; + String currentJoinPath; + + if (treatType != null) { + // Verify it's a valid type + treatJoinType = metamodel.getEntity(treatType); + currentJoinPath = "TREAT(" + baseNode.getAliasInfo().getAbsolutePath() + "." + joinRelationName + " AS " + treatJoinType.getName() + ")"; + } else { + treatJoinType = null; + currentJoinPath = baseNode.getAliasInfo().getAbsolutePath() + "." + joinRelationName; + } + if (node == null) { // a join node for the join relation does not yet exist checkAliasIsAvailable(alias, currentJoinPath, errorMessage); @@ -2310,7 +2324,7 @@ private JoinNode getOrCreate(JoinNode baseNode, String baseNodeTreatType, String JoinAliasInfo newAliasInfo = new JoinAliasInfo(alias, currentJoinPath, implicit, false, aliasManager); aliasManager.registerAliasInfo(newAliasInfo); - node = new JoinNode(baseNode, treeNode, baseNodeTreatType, newAliasInfo, type, joinRelationClass, treatType, qualificationExpression); + node = JoinNode.createAssociationJoinNode(baseNode, treeNode, type, joinRelationType, treatJoinType, qualificationExpression, newAliasInfo); newAliasInfo.setJoinNode(node); treeNode.addJoinNode(node, defaultJoin); } else { @@ -2336,8 +2350,10 @@ private JoinNode getOrCreate(JoinNode baseNode, String baseNodeTreatType, String } } - if (treatType != null) { - if (!treatType.equals(node.getTreatType())) { + if (treatJoinType != null) { + if (node.getTreatType() == null) { + node = node.getTreatedJoinNode(treatJoinType); + } else if (!treatJoinType.equals(node.getTreatType())) { throw new IllegalArgumentException("A join node [" + nodeAliasInfo.getAlias() + "=" + nodeAliasInfo.getAbsolutePath() + "] " + "for treat type [" + treatType + "] conflicts with the existing treat type [" + node.getTreatType() + "]"); } @@ -2395,35 +2411,21 @@ private static class JoinResult { final JoinNode baseNode; final List fields; - final String typeName; final Class type; final boolean lazy; - final boolean hasTreatedSubpath; public JoinResult(JoinNode baseNode, List fields, Class type) { - this(baseNode, fields, null, type); - } - - public JoinResult(JoinNode baseNode, List fields, String typeName, Class type) { this.baseNode = baseNode; this.fields = fields; - this.typeName = typeName; this.type = type; this.lazy = false; - this.hasTreatedSubpath = false; - } - - public JoinResult(JoinNode baseNode, List fields, Class type, boolean lazy, boolean hasTreatedSubpath) { - this(baseNode, fields, null, type, lazy, hasTreatedSubpath); } - public JoinResult(JoinNode baseNode, List fields, String typeName, Class type, boolean lazy, boolean hasTreatedSubpath) { + public JoinResult(JoinNode baseNode, List fields, Class type, boolean lazy) { this.baseNode = baseNode; this.fields = fields; - this.typeName = typeName; this.type = type; this.lazy = lazy; - this.hasTreatedSubpath = hasTreatedSubpath; } private boolean hasField() { diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinNode.java b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinNode.java index 3b27692d40..3cde61dd67 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/JoinNode.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/JoinNode.java @@ -37,6 +37,9 @@ import javax.persistence.Query; import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -56,7 +59,6 @@ */ public class JoinNode implements From, ExpressionModifier, BaseNode { - private JoinAliasInfo aliasInfo; private JoinType joinType = JoinType.LEFT; private boolean fetch = false; @@ -68,9 +70,8 @@ public class JoinNode implements From, ExpressionModifier, BaseNode { private final JoinNode correlationParent; private final String correlationPath; - private final String parentTreatType; - private final Class propertyClass; - private final String treatType; + private final Type nodeType; + private final EntityType treatType; private final String valuesFunction; private final int valueCount; private final int attributeCount; @@ -78,13 +79,15 @@ public class JoinNode implements From, ExpressionModifier, BaseNode { private final String valuesClause; private final String valuesAliases; private final String qualificationExpression; + private final JoinAliasInfo aliasInfo; + private final List joinNodesForTreatConstraint; - private final Map nodes = new TreeMap(); // Use TreeMap so that joins get applied - // alphabetically for easier testing - private final Set entityJoinNodes = new LinkedHashSet(); + private final Map nodes = new TreeMap<>(); // Use TreeMap so that joins get applied alphabetically for easier testing + private final Map treatedJoinNodes = new TreeMap<>(); + private final Set entityJoinNodes = new LinkedHashSet<>(); // contains other join nodes which this node depends on - private final Set dependencies = new HashSet(); + private final Set dependencies = new HashSet<>(); private CompoundPredicate onPredicate; @@ -92,65 +95,131 @@ public class JoinNode implements From, ExpressionModifier, BaseNode { private boolean dirty = true; private boolean cardinalityMandatory; - public JoinNode(JoinAliasInfo aliasInfo, Class propertyClass, String valuesFunction, int valueCount, int attributeCount, Query valueQuery, String valuesClause, String valuesAliases, String qualificationExpression) { - this.parent = null; - this.parentTreeNode = null; - this.parentTreatType = null; - this.aliasInfo = aliasInfo; - this.joinType = null; - this.propertyClass = propertyClass; - this.treatType = null; - this.valuesFunction = valuesFunction; - this.valueCount = valueCount; - this.attributeCount = attributeCount; - this.valueQuery = valueQuery; - this.valuesClause = valuesClause; - this.valuesAliases = valuesAliases; - this.correlationParent = null; - this.correlationPath = null; - this.qualificationExpression = qualificationExpression; - onUpdate(null); - } - - public JoinNode(JoinNode parent, JoinTreeNode parentTreeNode, String parentTreatType, JoinAliasInfo aliasInfo, JoinType joinType, Class propertyClass, String treatType, String qualificationExpression) { + private JoinNode(TreatedJoinAliasInfo treatedJoinAliasInfo) { + JoinNode treatedJoinNode = treatedJoinAliasInfo.getTreatedJoinNode(); + this.parent = treatedJoinNode.parent; + this.parentTreeNode = treatedJoinNode.parentTreeNode; + this.joinType = treatedJoinNode.joinType; + this.correlationParent = treatedJoinNode.correlationParent; + this.correlationPath = treatedJoinNode.correlationPath; + this.nodeType = treatedJoinNode.nodeType; + this.treatType = treatedJoinAliasInfo.getTreatType(); + this.qualificationExpression = treatedJoinNode.qualificationExpression; + this.valuesFunction = treatedJoinNode.valuesFunction; + this.valueCount = treatedJoinNode.valueCount; + this.attributeCount = treatedJoinNode.attributeCount; + this.valueQuery = treatedJoinNode.valueQuery; + this.valuesClause = treatedJoinNode.valuesClause; + this.valuesAliases = treatedJoinNode.valuesAliases; + this.aliasInfo = treatedJoinAliasInfo; + List joinNodesForTreatConstraint = new ArrayList<>(treatedJoinNode.joinNodesForTreatConstraint.size() + 1); + joinNodesForTreatConstraint.addAll(treatedJoinNode.joinNodesForTreatConstraint); + joinNodesForTreatConstraint.add(this); + this.joinNodesForTreatConstraint = Collections.unmodifiableList(joinNodesForTreatConstraint); + } + + private JoinNode(JoinNode parent, JoinTreeNode parentTreeNode, JoinType joinType, JoinNode correlationParent, String correlationPath, Type nodeType, EntityType treatType, String qualificationExpression, JoinAliasInfo aliasInfo) { this.parent = parent; this.parentTreeNode = parentTreeNode; - this.parentTreatType = parentTreatType; - this.aliasInfo = aliasInfo; this.joinType = joinType; - this.propertyClass = propertyClass; + this.correlationParent = correlationParent; + this.correlationPath = correlationPath; + this.nodeType = nodeType; this.treatType = treatType; - this.qualificationExpression = qualificationExpression; this.valuesFunction = null; this.valueCount = 0; this.attributeCount = 0; this.valueQuery = null; this.valuesClause = null; this.valuesAliases = null; - this.correlationParent = null; - this.correlationPath = null; + this.qualificationExpression = qualificationExpression; + this.aliasInfo = aliasInfo; + if (treatType != null) { + if (parent != null) { + List joinNodesForTreatConstraint = new ArrayList<>(parent.joinNodesForTreatConstraint.size() + 1); + joinNodesForTreatConstraint.addAll(parent.joinNodesForTreatConstraint); + joinNodesForTreatConstraint.add(this); + this.joinNodesForTreatConstraint = Collections.unmodifiableList(joinNodesForTreatConstraint); + } else { + this.joinNodesForTreatConstraint = Collections.singletonList(this); + } + } else { + if (parent != null) { + this.joinNodesForTreatConstraint = parent.joinNodesForTreatConstraint; + } else { + this.joinNodesForTreatConstraint = Collections.emptyList(); + } + } onUpdate(null); } - public JoinNode(JoinNode correlationParent, String correlationPath, String parentTreatType, JoinAliasInfo aliasInfo, Class propertyClass, String treatType, String qualificationExpression) { + private JoinNode(ManagedType nodeType, String valuesFunction, int valueCount, int attributeCount, Query valueQuery, String valuesClause, String valuesAliases, JoinAliasInfo aliasInfo) { this.parent = null; this.parentTreeNode = null; this.joinType = null; - this.correlationParent = correlationParent; - this.correlationPath = correlationPath; - this.parentTreatType = parentTreatType; + this.correlationParent = null; + this.correlationPath = null; + this.nodeType = nodeType; + this.treatType = null; + this.valuesFunction = valuesFunction; + this.valueCount = valueCount; + this.attributeCount = attributeCount; + this.valueQuery = valueQuery; + this.valuesClause = valuesClause; + this.valuesAliases = valuesAliases; + this.qualificationExpression = null; this.aliasInfo = aliasInfo; - this.propertyClass = propertyClass; - this.treatType = treatType; - this.valuesFunction = null; - this.valueCount = 0; - this.attributeCount = 0; - this.valueQuery = null; - this.valuesClause = null; - this.valuesAliases = null; - this.qualificationExpression = qualificationExpression; + this.joinNodesForTreatConstraint = Collections.emptyList(); onUpdate(null); } + + public static JoinNode createRootNode(EntityType nodeType, JoinAliasInfo aliasInfo) { + return new JoinNode(null, null, null, null, null, nodeType, null, null, aliasInfo); + } + + public static JoinNode createValuesRootNode(ManagedType nodeType, String valuesFunction, int valueCount, int attributeCount, Query valueQuery, String valuesClause, String valuesAliases, JoinAliasInfo aliasInfo) { + return new JoinNode(nodeType, valuesFunction, valueCount, attributeCount, valueQuery, valuesClause, valuesAliases, aliasInfo); + } + + public static JoinNode createCorrelationRootNode(JoinNode correlationParent, String correlationPath, ManagedType nodeType, EntityType treatType, JoinAliasInfo aliasInfo) { + return new JoinNode(null, null, null, correlationParent, correlationPath, nodeType, treatType, null, aliasInfo); + } + + public static JoinNode createEntityJoinNode(JoinNode parent, JoinType joinType, EntityType nodeType, JoinAliasInfo aliasInfo) { + return new JoinNode(parent, null, joinType, null, null, nodeType, null, null, aliasInfo); + } + + public static JoinNode createAssociationJoinNode(JoinNode parent, JoinTreeNode parentTreeNode, JoinType joinType, Type nodeType, EntityType treatType, String qualificationExpression, JoinAliasInfo aliasInfo) { + return new JoinNode(parent, parentTreeNode, joinType, null, null, nodeType, treatType, qualificationExpression, aliasInfo); + } + + public JoinNode cloneRootNode(JoinAliasInfo aliasInfo) { + // NOTE: no cloning of treatedJoinNodes and entityJoinNodes is intentional + JoinNode newNode; + if (valueQuery != null) { + newNode = createValuesRootNode((ManagedType) nodeType, valuesFunction, valueCount, attributeCount, valueQuery, valuesClause, valuesAliases, aliasInfo); + } else if (joinType == null) { + newNode = createRootNode((EntityType) nodeType, aliasInfo); + } else { + throw new UnsupportedOperationException("Cloning subqueries not yet implemented!"); + } + + return newNode; + } + + public JoinNode cloneJoinNode(JoinNode parent, JoinTreeNode parentTreeNode, JoinAliasInfo aliasInfo) { + // NOTE: no cloning of onPredicate, treatedJoinNodes and entityJoinNodes is intentional + JoinNode newNode; + if (parentTreeNode == null) { + newNode = createEntityJoinNode(parent, joinType, (EntityType) nodeType, aliasInfo); + } else { + newNode = createAssociationJoinNode(parent, parentTreeNode, joinType, nodeType, treatType, qualificationExpression, aliasInfo); + } + + newNode.fetch = fetch; + + return newNode; + } private void onUpdate(StateChange stateChange) { // Once mandatory, only a type change can cause a change of the cardinality mandatory @@ -275,6 +344,9 @@ public void accept(ExpressionModifierVisitor visitor for (JoinNode joinNode : entityJoinNodes) { joinNode.accept(visitor); } + for (JoinNode joinNode : treatedJoinNodes.values()) { + joinNode.accept(visitor); + } } public void accept(JoinNodeVisitor visitor) { @@ -287,6 +359,9 @@ public void accept(JoinNodeVisitor visitor) { for (JoinNode joinNode : entityJoinNodes) { joinNode.accept(visitor); } + for (JoinNode joinNode : treatedJoinNodes.values()) { + joinNode.accept(visitor); + } } public T accept(AbortableResultJoinNodeVisitor visitor) { @@ -312,10 +387,31 @@ public T accept(AbortableResultJoinNodeVisitor visitor) { return result; } } + for (JoinNode joinNode : treatedJoinNodes.values()) { + result = joinNode.accept(visitor); + + if (visitor.getStopValue().equals(result)) { + return result; + } + } return result; } + public JoinNode getTreatedJoinNode(EntityType type) { + String typeName = type.getJavaType().getName(); + JoinNode treatedNode = treatedJoinNodes.get(typeName); + if (treatedNode != null) { + return treatedNode; + } + + TreatedJoinAliasInfo treatedJoinAliasInfo = new TreatedJoinAliasInfo(this, type); + treatedNode = new JoinNode(treatedJoinAliasInfo); + treatedJoinAliasInfo.setJoinNode(treatedNode); + treatedJoinNodes.put(typeName, treatedNode); + return treatedNode; + } + public EnumSet getClauseDependencies() { return clauseDependencies; } @@ -332,10 +428,6 @@ public JoinAliasInfo getAliasInfo() { return aliasInfo; } - public void setAliasInfo(JoinAliasInfo aliasInfo) { - this.aliasInfo = aliasInfo; - } - public JoinType getJoinType() { return joinType; } @@ -357,6 +449,10 @@ public Map getNodes() { return nodes; } + public Map getTreatedJoinNodes() { + return treatedJoinNodes; + } + public JoinTreeNode getOrCreateTreeNode(String joinRelationName, Attribute attribute) { JoinTreeNode node = nodes.get(joinRelationName); @@ -376,18 +472,51 @@ public void addEntityJoin(JoinNode entityJoinNode) { entityJoinNodes.add(entityJoinNode); } - public String getParentTreatType() { - return parentTreatType; + public Type getNodeType() { + if (treatType != null) { + return treatType; + } + return nodeType; + } + + public EntityType getEntityType() { + if (treatType != null) { + return treatType; + } + if (nodeType instanceof EntityType) { + return (EntityType) nodeType; + } + + throw new IllegalArgumentException("Expected type of join node to be an entity but isn't: " + nodeType.getJavaType().getName()); } - public Class getPropertyClass() { - return propertyClass; + public ManagedType getManagedType() { + if (treatType != null) { + return treatType; + } + if (nodeType instanceof ManagedType) { + return (ManagedType) nodeType; + } + + throw new IllegalArgumentException("Expected type of join node to be a managed type but isn't: " + nodeType.getJavaType().getName()); } - public String getTreatType() { + public Type getBaseType() { + return nodeType; + } + + public EntityType getTreatType() { return treatType; } + public boolean isTreatJoinNode() { + return treatType != null && !(aliasInfo instanceof TreatedJoinAliasInfo); + } + + public boolean isTreatedJoinNode() { + return treatType != null && aliasInfo instanceof TreatedJoinAliasInfo; + } + public int getValueCount() { return valueCount; } @@ -445,6 +574,10 @@ public boolean hasCollections() { stack.addAll(node.getNodes().values()); } + for (JoinNode node : treatedJoinNodes.values()) { + stack.addAll(node.getNodes().values()); + } + while (!stack.isEmpty()) { JoinTreeNode treeNode = stack.remove(stack.size() - 1); @@ -471,6 +604,10 @@ Set getCollectionJoins() { stack.addAll(node.getNodes().values()); } + for (JoinNode node : treatedJoinNodes.values()) { + stack.addAll(node.getNodes().values()); + } + collectionJoins.addAll(entityJoinNodes); while (!stack.isEmpty()) { @@ -489,6 +626,10 @@ Set getCollectionJoins() { return collectionJoins; } + List getJoinNodesForTreatConstraint() { + return joinNodesForTreatConstraint; + } + public String getQualificationExpression() { return qualificationExpression; } @@ -534,7 +675,23 @@ public Expression createExpression(String field) { } } - public void appendAlias(StringBuilder sb, String property) { + public void appendDeReference(StringBuilder sb, String property) { + appendDeReference(sb, property, false); + } + + public void appendDeReference(StringBuilder sb, String property, boolean renderTreat) { + appendAlias(sb, renderTreat); + // If we have a valuesFunction, the property can only be "value" which is already handled in appendAlias + if (property != null && valuesFunction == null) { + sb.append('.').append(property); + } + } + + public void appendAlias(StringBuilder sb) { + appendAlias(sb, false); + } + + public void appendAlias(StringBuilder sb, boolean renderTreat) { if (valuesFunction != null) { // NOTE: property should always be null sb.append(valuesFunction).append('('); @@ -543,16 +700,33 @@ public void appendAlias(StringBuilder sb, String property) { sb.append(')'); } else { if (qualificationExpression != null) { + boolean hasTreat = renderTreat && treatType != null; + if (hasTreat) { + sb.append("TREAT("); + } + sb.append(qualificationExpression); sb.append('('); - sb.append(parent.getAlias()); + + if (renderTreat) { + parent.getAliasInfo().render(sb); + } else { + sb.append(parent.getAlias()); + } + sb.append(')'); - } else { - sb.append(aliasInfo.getAlias()); - } - if (property != null) { - sb.append('.').append(property); + if (hasTreat) { + sb.append(" AS "); + sb.append(treatType.getName()); + sb.append(')'); + } + } else { + if (renderTreat) { + aliasInfo.render(sb); + } else { + sb.append(aliasInfo.getAlias()); + } } } } @@ -566,7 +740,10 @@ public String getAlias() { @Override public Class getType() { - return propertyClass; + if (treatType != null) { + return treatType.getJavaType(); + } + return nodeType.getJavaType(); } public int getJoinDepth() { diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/JpaUtils.java b/core/impl/src/main/java/com/blazebit/persistence/impl/JpaUtils.java index 634034fa62..5f33182511 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/JpaUtils.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/JpaUtils.java @@ -320,11 +320,7 @@ public static AttributeHolder getAttributeForJoining(EntityMetamodel metamodel, } } - return getAttributeForJoining(metamodel, baseNode.getPropertyClass(), baseNode.getTreatType(), expression, baseNodeAlias); - } - - public static AttributeHolder getAttributeForJoining(EntityMetamodel metamodel, Class type, String treatTypeName, Expression joinExpression, String baseNodeAlias) { - return getAttributeForJoining(metamodel, getManagedType(metamodel, type, treatTypeName).getJavaType(), joinExpression, baseNodeAlias); + return getAttributeForJoining(metamodel, baseNode.getType(), expression, baseNodeAlias); } public static AttributeHolder getAttributeForJoining(EntityMetamodel metamodel, Class type, Expression joinExpression, String baseNodeAlias) { diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/PaginatedCriteriaBuilderImpl.java b/core/impl/src/main/java/com/blazebit/persistence/impl/PaginatedCriteriaBuilderImpl.java index d7866f4b47..d8d059535e 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/PaginatedCriteriaBuilderImpl.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/PaginatedCriteriaBuilderImpl.java @@ -468,10 +468,10 @@ protected String buildPageCountQueryString(boolean externalRepresentation) { private String buildPageCountQueryString(StringBuilder sbSelectFrom, boolean externalRepresentation) { JoinNode rootNode = joinManager.getRootNodeOrFail("Paginated criteria builders do not support multiple from clause elements!"); - Attribute idAttribute = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getPropertyClass())); + Attribute idAttribute = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getType())); String idName = idAttribute.getName(); StringBuilder idClause = new StringBuilder(100); - rootNode.appendAlias(idClause, idName); + rootNode.appendDeReference(idClause, idName); // Spaces are important to be able to reuse the string builder without copying String countString = jpaProvider.getCustomFunctionInvocation("COUNT_TUPLE", 1) + "'DISTINCT', " + idClause + ")"; sbSelectFrom.append("SELECT ").append(countString); @@ -526,9 +526,9 @@ private String appendSimplePageIdQueryString(StringBuilder sbSelectFrom) { queryGenerator.setAliasPrefix(PAGE_POSITION_ID_QUERY_ALIAS_PREFIX); JoinNode rootNode = joinManager.getRootNodeOrFail("Paginated criteria builders do not support multiple from clause elements!"); - String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getPropertyClass())).getName(); + String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getType())).getName(); StringBuilder idClause = new StringBuilder(PAGE_POSITION_ID_QUERY_ALIAS_PREFIX); - rootNode.appendAlias(idClause, idName); + rootNode.appendDeReference(idClause, idName); sbSelectFrom.append("SELECT ").append(idClause); // TODO: actually we should add the select clauses needed for order bys @@ -565,9 +565,9 @@ private String buildPageIdQueryString(boolean externalRepresentation) { private String buildPageIdQueryString(StringBuilder sbSelectFrom, boolean externalRepresentation) { JoinNode rootNode = joinManager.getRootNodeOrFail("Paginated criteria builders do not support multiple from clause elements!"); - String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getPropertyClass())).getName(); + String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getType())).getName(); StringBuilder idClause = new StringBuilder(100); - rootNode.appendAlias(idClause, idName); + rootNode.appendDeReference(idClause, idName); sbSelectFrom.append("SELECT ").append(idClause); @@ -622,7 +622,7 @@ protected String buildBaseQueryString(boolean externalRepresentation) { @Override protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean externalRepresentation) { JoinNode rootNode = joinManager.getRootNodeOrFail("Paginated criteria builders do not support multiple from clause elements!"); - String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getPropertyClass())).getName(); + String idName = JpaUtils.getIdAttribute(mainQuery.metamodel.entity(rootNode.getType())).getName(); selectManager.buildSelect(sbSelectFrom, false); @@ -635,7 +635,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external List whereClauseConjuncts = new ArrayList<>(); joinManager.buildClause(sbSelectFrom, EnumSet.complementOf(EnumSet.of(ClauseType.SELECT, ClauseType.ORDER_BY)), null, false, externalRepresentation, whereClauseConjuncts, explicitVersionEntities, nodesToFetch); sbSelectFrom.append(" WHERE "); - rootNode.appendAlias(sbSelectFrom, idName); + rootNode.appendDeReference(sbSelectFrom, idName); sbSelectFrom.append(" IN :").append(ID_PARAM_NAME).append(""); for (String conjunct : whereClauseConjuncts) { diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/ResolvingQueryGenerator.java b/core/impl/src/main/java/com/blazebit/persistence/impl/ResolvingQueryGenerator.java index f480d08e01..919f2fead1 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/ResolvingQueryGenerator.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/ResolvingQueryGenerator.java @@ -32,9 +32,20 @@ import com.blazebit.persistence.impl.expression.Subquery; import com.blazebit.persistence.impl.expression.SubqueryExpression; import com.blazebit.persistence.impl.expression.TreatExpression; +import com.blazebit.persistence.impl.predicate.BetweenPredicate; +import com.blazebit.persistence.impl.predicate.CompoundPredicate; import com.blazebit.persistence.impl.predicate.EqPredicate; +import com.blazebit.persistence.impl.predicate.ExistsPredicate; +import com.blazebit.persistence.impl.predicate.GePredicate; +import com.blazebit.persistence.impl.predicate.GtPredicate; import com.blazebit.persistence.impl.predicate.InPredicate; +import com.blazebit.persistence.impl.predicate.IsEmptyPredicate; import com.blazebit.persistence.impl.predicate.IsNullPredicate; +import com.blazebit.persistence.impl.predicate.LePredicate; +import com.blazebit.persistence.impl.predicate.LikePredicate; +import com.blazebit.persistence.impl.predicate.LtPredicate; +import com.blazebit.persistence.impl.predicate.MemberOfPredicate; +import com.blazebit.persistence.impl.predicate.Predicate; import com.blazebit.persistence.impl.predicate.PredicateQuantifier; import com.blazebit.persistence.impl.util.TypeConverter; import com.blazebit.persistence.impl.util.TypeUtils; @@ -46,6 +57,7 @@ import javax.persistence.metamodel.ManagedType; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -62,6 +74,7 @@ public class ResolvingQueryGenerator extends SimpleQueryGenerator { private boolean resolveSelectAliases = true; private Set renderedJoinNodes; private ClauseType clauseType; + private Map treatedJoinNodesForConstraints; private final AliasManager aliasManager; private final ParameterManager parameterManager; private final EntityMetamodel metamodel; @@ -306,13 +319,15 @@ public void visit(PathExpression expression) { } } } - if (expression.getBaseNode() == null) { + JoinNode baseNode; + String field; + if ((baseNode = (JoinNode) expression.getBaseNode()) == null) { super.visit(expression); - } else if (expression.getField() == null) { + } else if ((field = expression.getField()) == null) { if (expression.isUsedInCollectionFunction() || renderAbsolutePath(expression)) { super.visit(expression); } else { - boolean valueFunction = needsValueFunction(expression) && jpaProvider.getCollectionValueFunction() != null; + boolean valueFunction = needsValueFunction(expression, baseNode, field) && jpaProvider.getCollectionValueFunction() != null; if (valueFunction) { sb.append(jpaProvider.getCollectionValueFunction()); @@ -323,49 +338,83 @@ public void visit(PathExpression expression) { sb.append(aliasPrefix); } - JoinNode baseNode = (JoinNode) expression.getBaseNode(); - baseNode.appendAlias(sb, null); + baseNode.appendAlias(sb); if (valueFunction) { sb.append(')'); } } } else { - // Thats e.g. TREAT(TREAT(alias).property) - if (expression.hasTreatedSubpath()) { - // Actually we know that the treated subpath must be the first part of the path - expression.getExpressions().get(0).accept(this); - sb.append(".").append(expression.getField()); - } else { - boolean valueFunction = needsValueFunction(expression) && jpaProvider.getCollectionValueFunction() != null; - JoinNode baseNode = (JoinNode) expression.getBaseNode(); + List treatedJoinNodes = baseNode.getJoinNodesForTreatConstraint(); + if (treatedJoinNodesForConstraints != null) { + for (JoinNode node : treatedJoinNodes) { + treatedJoinNodesForConstraints.put(node, Boolean.FALSE); + } + } - if (valueFunction) { - sb.append(jpaProvider.getCollectionValueFunction()); - sb.append('('); + boolean addTypeCaseWhen = !treatedJoinNodes.isEmpty() + && jpaProvider.needsTypeConstraintForColumnSharing() + && jpaProvider.isColumnShared(baseNode.getManagedType(), field); + if (addTypeCaseWhen) { + sb.append("CASE WHEN "); + boolean first = true; - if (aliasPrefix != null) { - sb.append(aliasPrefix); + for (int i = 0; i < treatedJoinNodes.size(); i++) { + JoinNode treatedJoinNode = treatedJoinNodes.get(i); + + // When the JPA provider supports rendering treat joins and we have a treat join node + // we skip the type constraint as that is already applied through the join + if (jpaProvider.supportsTreatJoin() && treatedJoinNode.isTreatJoinNode()) { + continue; } - baseNode.appendAlias(sb, null); - sb.append(')'); - sb.append(".").append(expression.getField()); - } else { - if (aliasPrefix != null) { - sb.append(aliasPrefix); + if (first) { + first = false; + } else { + sb.append(" AND "); } - baseNode.appendAlias(sb, expression.getField()); + sb.append("TYPE("); + sb.append(treatedJoinNode.getAlias()); + sb.append(") = "); + sb.append(treatedJoinNode.getTreatType().getName()); } + + sb.append(" THEN "); } + boolean valueFunction = needsValueFunction(expression, baseNode, field) && jpaProvider.getCollectionValueFunction() != null; + // NOTE: There is no need to check for whether the JPA provider support implicit downcasting here + // If it didn't, the query building would have already failed before. Here we just decide whether to render the treat or not + boolean renderTreat = jpaProvider.supportsRootTreat(); + + if (valueFunction) { + sb.append(jpaProvider.getCollectionValueFunction()); + sb.append('('); + + if (aliasPrefix != null) { + sb.append(aliasPrefix); + } + + baseNode.appendAlias(sb, renderTreat); + sb.append(')'); + sb.append(".").append(field); + } else { + if (aliasPrefix != null) { + sb.append(aliasPrefix); + } + + baseNode.appendDeReference(sb, field, renderTreat); + } + + if (addTypeCaseWhen) { + sb.append(" END"); + } } } - private boolean needsValueFunction(PathExpression expression) { - JoinNode baseNode = (JoinNode) expression.getBaseNode(); - return !expression.isCollectionKeyPath() && baseNode.getParentTreeNode() != null && baseNode.getParentTreeNode().isMap() && (expression.getField() == null || jpaProvider.supportsCollectionValueDereference()); + private boolean needsValueFunction(PathExpression expression, JoinNode baseNode, String field) { + return !expression.isCollectionKeyPath() && baseNode.getParentTreeNode() != null && baseNode.getParentTreeNode().isMap() && (field == null || jpaProvider.supportsCollectionValueDereference()); } private boolean renderAbsolutePath(PathExpression expression) { @@ -457,6 +506,7 @@ public void visit(InPredicate predicate) { Class associationType = getAssociationType(predicate.getLeft(), right); ParameterManager.ParameterValueTranformer tranformer = parameterTransformerFactory.getToEntityTranformer(associationType); param.setTranformer(tranformer); + renderEquality(predicate.getLeft(), right, predicate.isNegated(), PredicateQuantifier.ONE); } else if (right instanceof PathExpression) { renderEquality(predicate.getLeft(), right, predicate.isNegated(), PredicateQuantifier.ONE); } @@ -476,6 +526,9 @@ private Class getAssociationType(Expression expression1, Expression expressio @Override public void visit(final EqPredicate predicate) { renderEquality(predicate.getLeft(), predicate.getRight(), predicate.isNegated(), predicate.getQuantifier()); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } } private void renderEquality(Expression left, Expression right, boolean negated, PredicateQuantifier quantifier) { @@ -552,9 +605,200 @@ public void visit(IsNullPredicate predicate) { predicate.getExpression().accept(this); if (predicate.isNegated()) { sb.append(" IS NOT NULL"); + flipTreatedJoinNodeConstraints(); } else { sb.append(" IS NULL"); } setParameterRenderingMode(oldParameterRenderingMode); } + + @Override + public void visit(IsEmptyPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(MemberOfPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(LikePredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(BetweenPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(ExistsPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(GtPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(GePredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(LtPredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(LePredicate predicate) { + super.visit(predicate); + if (predicate.isNegated()) { + flipTreatedJoinNodeConstraints(); + } + } + + @Override + public void visit(CompoundPredicate predicate) { + BooleanLiteralRenderingContext oldConditionalContext = setBooleanLiteralRenderingContext(BooleanLiteralRenderingContext.PREDICATE); + ParameterRenderingMode oldParameterRenderingMode = setParameterRenderingMode(ParameterRenderingMode.PLACEHOLDER); + boolean parenthesisRequired = predicate.getChildren().size() > 1; + if (predicate.isNegated()) { + sb.append("NOT "); + if (parenthesisRequired) { + sb.append('('); + } + } + + if (predicate.getChildren().size() == 1) { + int startPosition = sb.length(); + Map oldTreatedJoinNodesForConstraints = treatedJoinNodesForConstraints; + treatedJoinNodesForConstraints = new LinkedHashMap<>(); + + predicate.getChildren().get(0).accept(this); + + insertTreatJoinConstraint(startPosition, sb.length()); + treatedJoinNodesForConstraints = oldTreatedJoinNodesForConstraints; + return; + } + final int startLen = sb.length(); + final String operator = " " + predicate.getOperator().toString() + " "; + final List children = predicate.getChildren(); + int size = children.size(); + Map oldTreatedJoinNodesForConstraints = treatedJoinNodesForConstraints; + treatedJoinNodesForConstraints = new LinkedHashMap<>(); + for (int i = 0; i < size; i++) { + int startPosition = sb.length(); + int endPosition; + + Predicate child = children.get(i); + if (child instanceof CompoundPredicate && ((CompoundPredicate) child).getOperator() != predicate.getOperator() && !child.isNegated()) { + sb.append("("); + int len = sb.length(); + child.accept(this); + // If the child was empty, we remove the opening parenthesis again + if (len == sb.length()) { + sb.deleteCharAt(len - 1); + endPosition = sb.length(); + } else { + sb.append(")"); + endPosition = sb.length(); + sb.append(operator); + } + } else { + child.accept(this); + endPosition = sb.length(); + sb.append(operator); + } + + insertTreatJoinConstraint(startPosition, endPosition); + treatedJoinNodesForConstraints.clear(); + } + + treatedJoinNodesForConstraints = oldTreatedJoinNodesForConstraints; + + // Delete the last operator only if the children actually generated something + if (startLen < sb.length()) { + sb.delete(sb.length() - operator.length(), sb.length()); + } + if (predicate.isNegated() && parenthesisRequired) { + sb.append(')'); + } + setBooleanLiteralRenderingContext(oldConditionalContext); + setParameterRenderingMode(oldParameterRenderingMode); + } + + private void flipTreatedJoinNodeConstraints() { + if (treatedJoinNodesForConstraints != null) { + for (Map.Entry entry : treatedJoinNodesForConstraints.entrySet()) { + if (entry.getValue() == Boolean.TRUE) { + entry.setValue(Boolean.FALSE); + } else { + entry.setValue(Boolean.TRUE); + } + } + } + } + + private boolean insertTreatJoinConstraint(int startPosition, int endPosition) { + if (!treatedJoinNodesForConstraints.isEmpty()) { + StringBuilder treatConditionBuilder = new StringBuilder(treatedJoinNodesForConstraints.size() * 40); + treatConditionBuilder.append('('); + for (Map.Entry entry : treatedJoinNodesForConstraints.entrySet()) { + JoinNode node = entry.getKey(); + // When the JPA provider supports rendering treat joins and we have a treat join node + // we skip the type constraint as that is already applied through the join + if (jpaProvider.supportsTreatJoin() && node.isTreatJoinNode()) { + continue; + } + + treatConditionBuilder.append("TYPE("); + treatConditionBuilder.append(node.getAlias()); + if (entry.getValue() == Boolean.TRUE) { + treatConditionBuilder.append(") <> "); + treatConditionBuilder.append(node.getTreatType().getName()); + treatConditionBuilder.append(" OR "); + } else { + treatConditionBuilder.append(") = "); + treatConditionBuilder.append(node.getTreatType().getName()); + treatConditionBuilder.append(" AND "); + } + } + + // Because we always have the open parenthesis as first char + if (treatConditionBuilder.length() > 1) { + sb.insert(endPosition, ')'); + sb.insert(startPosition, treatConditionBuilder); + return true; + } + } + + return false; + } } diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/SelectManager.java b/core/impl/src/main/java/com/blazebit/persistence/impl/SelectManager.java index 929c5dd3fb..51ce469b4b 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/SelectManager.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/SelectManager.java @@ -208,7 +208,7 @@ void buildGroupByClauses(final EntityMetamodel m, Set clauses) { String rootAlias = rootNode.getAliasInfo().getAlias(); List path = Arrays.asList((PathElementExpression) new PropertyExpression(rootAlias)); - resolveVisitor.visit(new PathExpression(path, new SimplePathReference(rootNode, null, null, rootNode.getPropertyClass()), false, false)); + resolveVisitor.visit(new PathExpression(path, new SimplePathReference(rootNode, null, rootNode.getType()), false, false)); queryGenerator.setClauseType(ClauseType.GROUP_BY); queryGenerator.setQueryBuffer(sb); @@ -268,7 +268,7 @@ void buildSelect(StringBuilder sb, boolean isInsertInto) { int size = selectInfos.size(); if (size == 0) { JoinNode rootNode = joinManager.getRootNodeOrFail("Empty select not allowed when having multiple roots!"); - rootNode.appendAlias(sb, null); + rootNode.appendAlias(sb); } else { // we must not replace select alias since we would loose the original expressions queryGenerator.setClauseType(ClauseType.SELECT); diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/TreatedJoinAliasInfo.java b/core/impl/src/main/java/com/blazebit/persistence/impl/TreatedJoinAliasInfo.java new file mode 100644 index 0000000000..edf7e40f1f --- /dev/null +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/TreatedJoinAliasInfo.java @@ -0,0 +1,62 @@ +/* + * Copyright 2014 - 2017 Blazebit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.blazebit.persistence.impl; + +import javax.persistence.metamodel.EntityType; + +/** + * This is the join alias info for "special" join nodes that aren't rendered as joins + * but only serve for providing a "treat-view" on an existing join node. + * + * @author Christian Beikov + * @since 1.2.0 + */ +public class TreatedJoinAliasInfo extends JoinAliasInfo { + + private final JoinNode treatedJoinNode; + private final EntityType treatType; + + public TreatedJoinAliasInfo(JoinNode treatedJoinNode, EntityType treatType) { + super( + treatedJoinNode.getAlias(), + "TREAT(" + treatedJoinNode.getAliasInfo().getAbsolutePath() + " AS " + treatType.getName() + ")", + treatedJoinNode.getAliasInfo().isImplicit(), + treatedJoinNode.getAliasInfo().isRootNode(), + treatedJoinNode.getAliasInfo().getAliasOwner() + ); + this.treatedJoinNode = treatedJoinNode; + this.treatType = treatType; + } + + public JoinNode getTreatedJoinNode() { + return treatedJoinNode; + } + + public EntityType getTreatType() { + return treatType; + } + + @Override + public String getAbsolutePath() { + return "TREAT(" + treatedJoinNode.getAliasInfo().getAbsolutePath() + " AS " + treatType.getName() + ")"; + } + + @Override + public void render(StringBuilder sb) { + sb.append("TREAT(").append(treatedJoinNode.getAliasInfo().getAlias()).append(" AS ").append(treatType.getName()).append(')'); + } +} diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformationVisitor.java b/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformationVisitor.java index 4df93533c3..615c7c1b22 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformationVisitor.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformationVisitor.java @@ -47,6 +47,7 @@ import javax.persistence.metamodel.IdentifiableType; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; import javax.persistence.metamodel.Type.PersistenceType; import java.util.*; @@ -160,16 +161,19 @@ private boolean requiresBlacklistedNode(PathExpression sizeArg) { private Expression getSizeExpression(ExpressionModifier parentModifier, PathExpression sizeArg) { JoinNode sizeArgJoin = (JoinNode) sizeArg.getBaseNode(); String property = sizeArg.getPathReference().getField(); - Class startClass = ((JoinNode) sizeArg.getBaseNode()).getPropertyClass(); + final Type nodeType = ((JoinNode) sizeArg.getBaseNode()).getBaseType(); + if (!(nodeType instanceof EntityType)) { + throw new IllegalArgumentException("Size on a collection owned by a non-entity type is not supported yet: " + sizeArg); + } + final EntityType startType = (EntityType) nodeType; AttributeHolder result = JpaUtils.getAttributeForJoining(metamodel, sizeArg); PluralAttribute targetAttribute = (PluralAttribute) result.getAttribute(); if (targetAttribute == null) { - throw new RuntimeException("Attribute [" + property + "] not found on class " + startClass.getName()); + throw new RuntimeException("Attribute [" + property + "] not found on class " + startType.getJavaType().getName()); } final PluralAttribute.CollectionType collectionType = targetAttribute.getCollectionType(); final boolean isElementCollection = targetAttribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.ELEMENT_COLLECTION; - final EntityType startType = metamodel.entity(startClass); boolean subqueryRequired; if (isElementCollection) { @@ -185,14 +189,14 @@ private Expression getSizeExpression(ExpressionModifier parentModifier, PathExpr // build group by id clause List pathElementExpr = new ArrayList(); - String rootId = JpaUtils.getIdAttribute(metamodel.entity(startClass)).getName(); + String rootId = JpaUtils.getIdAttribute(startType).getName(); pathElementExpr.add(new PropertyExpression(sizeArgJoin.getAlias())); pathElementExpr.add(new PropertyExpression(rootId)); PathExpression groupByExpr = new PathExpression(pathElementExpr); String groupByExprString = groupByExpr.toString(); subqueryRequired = subqueryRequired || - !metamodel.entity(startClass).hasSingleIdAttribute() || + !startType.hasSingleIdAttribute() || joinManager.getRoots().size() > 1 || clause == ClauseType.JOIN || !isCountTransformationEnabled() || @@ -280,7 +284,8 @@ private Expression getSizeExpression(ExpressionModifier parentModifier, PathExpr AggregateExpression transformedExpr = transformedExpressionEntry.getTransformedExpression(); if (ExpressionUtils.isCustomFunctionInvocation(transformedExpr) && AbstractCountFunction.FUNCTION_NAME.equalsIgnoreCase(((StringLiteral) transformedExpr.getExpressions().get(0)).getValue())) { - if (!AbstractCountFunction.DISTINCT_QUALIFIER.equals(transformedExpr.getExpressions().get(1))) { + Expression possibleDistinct = transformedExpr.getExpressions().get(1); + if (!(possibleDistinct instanceof StringLiteral) || !AbstractCountFunction.DISTINCT_QUALIFIER.equals(((StringLiteral) possibleDistinct).getValue())) { transformedExpr.getExpressions().add(1, new StringLiteral(AbstractCountFunction.DISTINCT_QUALIFIER)); } } else { @@ -311,14 +316,18 @@ private AggregateExpression createCountFunction(boolean distinct, List startClass = sizeArgJoin.getPropertyClass(); + final Type nodeType = sizeArgJoin.getNodeType(); + if (!(nodeType instanceof EntityType)) { + throw new IllegalArgumentException("Size on a collection owned by a non-entity type is not supported yet: " + sizeArg); + } + final EntityType startType = (EntityType) nodeType; Subquery countSubquery = (Subquery) subqueryInitFactory.createSubqueryInitiator(null, new SubqueryBuilderListenerImpl(), false) .from(sizeArg.clone(true).toString()) .select("COUNT(*)"); List pathElementExpr = new ArrayList(); - String rootId = JpaUtils.getIdAttribute(metamodel.entity(startClass)).getName(); + String rootId = JpaUtils.getIdAttribute(startType).getName(); pathElementExpr.add(new PropertyExpression(sizeArgJoin.getAlias())); pathElementExpr.add(new PropertyExpression(rootId)); PathExpression groupByExpr = new PathExpression(pathElementExpr); diff --git a/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformerGroup.java b/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformerGroup.java index c0057e9a64..628f65c3c3 100644 --- a/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformerGroup.java +++ b/core/impl/src/main/java/com/blazebit/persistence/impl/transform/SizeTransformerGroup.java @@ -84,7 +84,7 @@ public void afterGlobalTransformation() { PathReference generatedJoin = requiredJoinExpression.getPathReference(); ((JoinNode) generatedJoin.getBaseNode()).getClauseDependencies().addAll(lateJoinEntry.getClauseDependencies()); for (int i = 1; i < lateJoinEntry.getPathsToJoin().size(); i++) { - lateJoinEntry.getPathsToJoin().get(i).setPathReference(new SimplePathReference(generatedJoin.getBaseNode(), generatedJoin.getField(), null, generatedJoin.getType())); + lateJoinEntry.getPathsToJoin().get(i).setPathReference(new SimplePathReference(generatedJoin.getBaseNode(), generatedJoin.getField(), generatedJoin.getType())); } } } diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/EntityMetamodel.java b/core/parser/src/main/java/com/blazebit/persistence/impl/EntityMetamodel.java index eade99a8f3..783337cfe3 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/EntityMetamodel.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/EntityMetamodel.java @@ -19,6 +19,7 @@ import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; +import javax.persistence.metamodel.Type; /** * This is a wrapper around the JPA {@link javax.persistence.metamodel.Metamodel} that allows additionally efficient access by other attributes than a Class. @@ -38,4 +39,5 @@ public interface EntityMetamodel extends Metamodel { public ManagedType getManagedType(Class cls); + public Type type(Class cls); } diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/SimpleQueryGenerator.java b/core/parser/src/main/java/com/blazebit/persistence/impl/SimpleQueryGenerator.java index f8e1b27fe8..f0ea7ab502 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/SimpleQueryGenerator.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/SimpleQueryGenerator.java @@ -152,10 +152,10 @@ protected String escapeCharacter(char character) { public void visit(final CompoundPredicate predicate) { BooleanLiteralRenderingContext oldConditionalContext = setBooleanLiteralRenderingContext(BooleanLiteralRenderingContext.PREDICATE); ParameterRenderingMode oldParameterRenderingMode = setParameterRenderingMode(ParameterRenderingMode.PLACEHOLDER); - boolean paranthesisRequired = predicate.getChildren().size() > 1; + boolean parenthesisRequired = predicate.getChildren().size() > 1; if (predicate.isNegated()) { sb.append("NOT "); - if (paranthesisRequired) { + if (parenthesisRequired) { sb.append('('); } } @@ -165,7 +165,7 @@ public void visit(final CompoundPredicate predicate) { return; } final int startLen = sb.length(); - final String and = " " + predicate.getOperator().toString() + " "; + final String operator = " " + predicate.getOperator().toString() + " "; List children = predicate.getChildren(); int size = children.size(); for (int i = 0; i < size; i++) { @@ -174,26 +174,24 @@ public void visit(final CompoundPredicate predicate) { sb.append("("); int len = sb.length(); child.accept(this); + // If the child was empty, we remove the opening parenthesis again if (len == sb.length()) { sb.deleteCharAt(len - 1); } else { sb.append(")"); - sb.append(and); + sb.append(operator); } - } else { - int len = sb.length(); child.accept(this); - if (len < sb.length()) { - sb.append(and); - } + sb.append(operator); } } + // Delete the last operator only if the children actually generated something if (startLen < sb.length()) { - sb.delete(sb.length() - and.length(), sb.length()); + sb.delete(sb.length() - operator.length(), sb.length()); } - if (predicate.isNegated() && paranthesisRequired) { + if (predicate.isNegated() && parenthesisRequired) { sb.append(')'); } setBooleanLiteralRenderingContext(oldConditionalContext); diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/AbstractExpressionFactory.java b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/AbstractExpressionFactory.java index 040bfb218a..e460effdd5 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/AbstractExpressionFactory.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/AbstractExpressionFactory.java @@ -90,7 +90,12 @@ private Expression createExpression(RuleInvoker ruleInvoker, String expression, CommonTokenStream tokens = new CommonTokenStream(l); JPQLSelectExpressionParser p = new JPQLSelectExpressionParser(tokens, allowCaseWhen, allowQuantifiedPredicates, allowTreatJoinExtension); configureParser(p); - ParserRuleContext ctx = ruleInvoker.invokeRule(p); + ParserRuleContext ctx; + try { + ctx = ruleInvoker.invokeRule(p); + } catch (SyntaxErrorException ex) { + throw new SyntaxErrorException("Could not parse expression '" + expression + "', " + ex.getMessage(), ex); + } if (LOG.isLoggable(Level.FINEST)) { LOG.finest(ctx.toStringTree()); diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathExpression.java b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathExpression.java index 649d027112..cb6d2ecbe9 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathExpression.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathExpression.java @@ -132,14 +132,6 @@ public void setCollectionKeyPath(boolean collectionKeyPath) { this.collectionKeyPath = collectionKeyPath; } - public boolean hasTreatedSubpath() { - return hasTreatedSubpath; - } - - public void setHasTreatedSubpath(boolean hasTreatedSubpath) { - this.hasTreatedSubpath = hasTreatedSubpath; - } - /* * The following equals and hashCode implementation makes it possible that expressions which have different path properties but * reference the same object, are equal. diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathReference.java b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathReference.java index 7ad9df5846..228831166e 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathReference.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/PathReference.java @@ -30,8 +30,6 @@ public interface PathReference { public String getField(); - public String getTreatTypeName(); - /** * Returns the type of the path reference. * diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SimplePathReference.java b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SimplePathReference.java index f3f26ca04e..44e96a8866 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SimplePathReference.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SimplePathReference.java @@ -21,13 +21,11 @@ public class SimplePathReference implements PathReference { private final BaseNode baseNode; private final String field; - private final String typeName; private final Class type; - public SimplePathReference(BaseNode baseNode, String field, String typeName, Class type) { + public SimplePathReference(BaseNode baseNode, String field, Class type) { this.baseNode = baseNode; this.field = field; - this.typeName = typeName; this.type = type; } @@ -41,11 +39,6 @@ public String getField() { return field; } - @Override - public String getTreatTypeName() { - return typeName; - } - @Override public Class getType() { return type; @@ -57,7 +50,6 @@ public int hashCode() { int result = 1; result = prime * result + ((baseNode == null) ? 0 : baseNode.hashCode()); result = prime * result + ((field == null) ? 0 : field.hashCode()); - result = prime * result + ((typeName == null) ? 0 : typeName.hashCode()); return result; } @@ -87,13 +79,6 @@ public boolean equals(Object obj) { } else if (!field.equals(other.getField())) { return false; } - if (typeName == null) { - if (other.getTreatTypeName() != null) { - return false; - } - } else if (!typeName.equals(other.getTreatTypeName())) { - return false; - } return true; } diff --git a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SyntaxErrorException.java b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SyntaxErrorException.java index 5f73e06471..e31d2bc47f 100644 --- a/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SyntaxErrorException.java +++ b/core/parser/src/main/java/com/blazebit/persistence/impl/expression/SyntaxErrorException.java @@ -36,4 +36,8 @@ public SyntaxErrorException(Throwable t) { public SyntaxErrorException(String msg) { super(msg); } + + public SyntaxErrorException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/core/testsuite/pom.xml b/core/testsuite/pom.xml index b04d34f9d4..93962a614d 100644 --- a/core/testsuite/pom.xml +++ b/core/testsuite/pom.xml @@ -100,6 +100,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -134,6 +153,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -168,6 +206,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -202,6 +259,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -241,6 +317,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -282,6 +377,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -319,6 +433,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -353,6 +486,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + @@ -369,6 +521,7 @@ hibernate com.blazebit.persistence.testsuite.base.category.NoHibernate,com.blazebit.persistence.testsuite.base.category.NoHibernate42 + src/main/hibernate true @@ -399,35 +552,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - ${processor.plugin.compilerArguments} - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - 1.3.0.Final - - - org.codehaus.mojo build-helper-maven-plugin @@ -440,7 +564,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -459,6 +583,35 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + ${processor.plugin.compilerArguments} + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + 1.3.0.Final + + + @@ -466,6 +619,7 @@ hibernate-4.3 com.blazebit.persistence.testsuite.base.category.NoHibernate,com.blazebit.persistence.testsuite.base.category.NoHibernate43 + src/main/hibernate @@ -493,34 +647,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - ${version.hibernate-4.3} - - - org.codehaus.mojo build-helper-maven-plugin @@ -533,7 +659,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -552,6 +678,34 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + ${version.hibernate-4.3} + + + @@ -559,6 +713,7 @@ hibernate-5.0 com.blazebit.persistence.testsuite.base.category.NoHibernate,com.blazebit.persistence.testsuite.base.category.NoHibernate50 + src/main/hibernate @@ -586,34 +741,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - ${version.hibernate-5} - - - org.codehaus.mojo build-helper-maven-plugin @@ -626,7 +753,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -645,6 +772,34 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + ${version.hibernate-5} + + + @@ -652,6 +807,7 @@ hibernate-5.1 com.blazebit.persistence.testsuite.base.category.NoHibernate,com.blazebit.persistence.testsuite.base.category.NoHibernate51 + src/main/hibernate @@ -679,34 +835,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - ${version.hibernate-5.1} - - - org.codehaus.mojo build-helper-maven-plugin @@ -719,7 +847,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -738,6 +866,34 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + ${version.hibernate-5.1} + + + @@ -745,6 +901,7 @@ hibernate-5.2 com.blazebit.persistence.testsuite.base.category.NoHibernate,com.blazebit.persistence.testsuite.base.category.NoHibernate52 + src/main/hibernate @@ -772,34 +929,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - ${version.hibernate-5.2} - - - org.codehaus.mojo build-helper-maven-plugin @@ -812,7 +941,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -831,6 +960,34 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + ${version.hibernate-5.2} + + + @@ -838,6 +995,7 @@ hibernate-6.0 com.blazebit.persistence.testsuite.base.category.NoHibernate + src/main/hibernate @@ -872,34 +1030,6 @@ - - org.bsc.maven - maven-processor-plugin - - - process - - process - - generate-sources - - - ${project.build.directory}/test-metamodel - - org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor - - - - - - - - org.hibernate - hibernate-jpamodelgen - ${version.hibernate-6.0} - - - org.codehaus.mojo build-helper-maven-plugin @@ -912,7 +1042,7 @@ - src/main/hibernate + ${additional.source.directory} ${project.build.directory}/test-metamodel @@ -931,6 +1061,34 @@ + + org.bsc.maven + maven-processor-plugin + + + process + + process + + generate-sources + + + ${project.build.directory}/test-metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.hibernate + hibernate-jpamodelgen + ${version.hibernate-6.0} + + + @@ -938,6 +1096,7 @@ eclipselink com.blazebit.persistence.testsuite.base.category.NoEclipselink + src/main/basic @@ -960,6 +1119,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + org.bsc.maven maven-processor-plugin @@ -991,25 +1169,6 @@ - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - src/main/basic - ${project.build.directory}/test-metamodel - - - - - @@ -1017,6 +1176,7 @@ datanucleus-4 com.blazebit.persistence.testsuite.base.category.NoDatanucleus,com.blazebit.persistence.testsuite.base.category.NoDatanucleus4 + src/main/basic @@ -1096,6 +1256,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + org.bsc.maven maven-processor-plugin @@ -1124,25 +1303,6 @@ - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - src/main/basic - ${project.build.directory}/test-metamodel - - - - - @@ -1150,6 +1310,7 @@ datanucleus-5 com.blazebit.persistence.testsuite.base.category.NoDatanucleus + src/main/basic @@ -1222,40 +1383,40 @@ - org.bsc.maven - maven-processor-plugin + org.codehaus.mojo + build-helper-maven-plugin - process + add-source + generate-sources - process + add-source - generate-sources - - ${project.build.directory}/test-metamodel - - org.datanucleus.jpa.query.JPACriteriaProcessor - + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + - org.codehaus.mojo - build-helper-maven-plugin + org.bsc.maven + maven-processor-plugin - add-source - generate-sources + process - add-source + process + generate-sources - - src/main/basic - ${project.build.directory}/test-metamodel - + + ${project.build.directory}/test-metamodel + + org.datanucleus.jpa.query.JPACriteriaProcessor + @@ -1267,6 +1428,7 @@ openjpa com.blazebit.persistence.testsuite.base.category.NoOpenJPA + src/main/basic @@ -1282,6 +1444,25 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${additional.source.directory} + ${project.build.directory}/test-metamodel + + + + + org.bsc.maven maven-processor-plugin @@ -1312,25 +1493,6 @@ - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - src/main/basic - ${project.build.directory}/test-metamodel - - - - - diff --git a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub1.java b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub1.java index 2fbc6bc6e0..c4fc2b5b07 100644 --- a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub1.java +++ b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub1.java @@ -87,6 +87,7 @@ public void setSub1List(List sub1List) { @Override @OneToMany + @JoinTable(name = "single_table_embeddable_1_sub_children") @JoinColumn(name = "embeddableSub1Parent") public Set getSub1Children() { return sub1Children; diff --git a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub2.java b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub2.java index 8dc9856241..33b013cc18 100644 --- a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub2.java +++ b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/SingleTableEmbeddableSub2.java @@ -87,6 +87,7 @@ public void setSub2List(List sub2List) { @Override @OneToMany + @JoinTable(name = "single_table_embeddable_2_sub_children") @JoinColumn(name = "embeddableSub2Parent") public Set getSub2Children() { return sub2Children; diff --git a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/TablePerClassBase.java b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/TablePerClassBase.java index b5c81a03e1..c4041e447a 100644 --- a/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/TablePerClassBase.java +++ b/core/testsuite/src/main/basic/com/blazebit/persistence/testsuite/treat/entity/TablePerClassBase.java @@ -21,7 +21,6 @@ import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.ForeignKey; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; @@ -49,13 +48,13 @@ public abstract class TablePerClassBase implements Serializable, Base type, String property) { protected String treatJoin(String path, Class type) { if (jpaProvider.supportsTreatJoin()) { return "TREAT(" + path + " AS " + type.getSimpleName() + ")"; - } else if (jpaProvider.supportsSubtypePropertyResolving()) { + } else if (jpaProvider.supportsSubtypeRelationResolving()) { return path; } @@ -232,7 +221,7 @@ protected String treatJoin(String path, Class type) { protected String treatRootJoin(String path, Class type, String property) { if (jpaProvider.supportsRootTreatJoin()) { return "TREAT(" + path + " AS " + type.getSimpleName() + ")." + property; - } else if (jpaProvider.supportsSubtypePropertyResolving()) { + } else if (jpaProvider.supportsSubtypeRelationResolving()) { return path + "." + property; } diff --git a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassBase.java b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCBase.java similarity index 87% rename from core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassBase.java rename to core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCBase.java index f805de6e23..99c2cb744e 100644 --- a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassBase.java +++ b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCBase.java @@ -29,21 +29,21 @@ */ @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public abstract class TablePerClassBase implements Serializable { +public abstract class TPCBase implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String base; - public TablePerClassBase() { + public TPCBase() { } - public TablePerClassBase(Long id) { + public TPCBase(Long id) { this.id = id; } - public TablePerClassBase(Long id, String base) { + public TPCBase(Long id, String base) { this.id = id; this.base = base; } diff --git a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub1.java b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub1.java similarity index 88% rename from core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub1.java rename to core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub1.java index 4a66678d91..ff2ccfa1af 100644 --- a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub1.java +++ b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub1.java @@ -24,16 +24,16 @@ * @since 1.2.0 */ @Entity -public class TablePerClassSub1 extends TablePerClassBase { +public class TPCSub1 extends TPCBase { private static final long serialVersionUID = 1L; private String name; private int sub1; - public TablePerClassSub1() { + public TPCSub1() { } - public TablePerClassSub1(Long id, String base) { + public TPCSub1(Long id, String base) { super(id, base); } diff --git a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub2.java b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub2.java similarity index 88% rename from core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub2.java rename to core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub2.java index 88068d9f52..55d39b0815 100644 --- a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TablePerClassSub2.java +++ b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/TPCSub2.java @@ -24,16 +24,16 @@ * @since 1.2.0 */ @Entity -public class TablePerClassSub2 extends TablePerClassBase { +public class TPCSub2 extends TPCBase { private static final long serialVersionUID = 1L; private String name; private int sub2; - public TablePerClassSub2() { + public TPCSub2() { } - public TablePerClassSub2(Long id, String base) { + public TPCSub2(Long id, String base) { super(id, base); } diff --git a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/treat/entity/IntIdEntity.java b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/treat/entity/IntIdEntity.java index b911830b43..10d725d342 100644 --- a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/treat/entity/IntIdEntity.java +++ b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/treat/entity/IntIdEntity.java @@ -67,18 +67,23 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } IntIdEntity other = (IntIdEntity) obj; if (id == null) { - if (other.id != null) + if (other.id != null) { return false; - } else if (!id.equals(other.id)) + } + } else if (!id.equals(other.id)) { return false; + } return true; } } diff --git a/core/testsuite/src/main/resources/META-INF/persistence.xml b/core/testsuite/src/main/resources/META-INF/persistence.xml index 2225e610a1..acd9b35330 100644 --- a/core/testsuite/src/main/resources/META-INF/persistence.xml +++ b/core/testsuite/src/main/resources/META-INF/persistence.xml @@ -74,9 +74,9 @@ com.blazebit.persistence.testsuite.entity.SequenceBaseEntity com.blazebit.persistence.testsuite.entity.SmallProject com.blazebit.persistence.testsuite.entity.StringIdCTE - com.blazebit.persistence.testsuite.entity.TablePerClassBase - com.blazebit.persistence.testsuite.entity.TablePerClassSub1 - com.blazebit.persistence.testsuite.entity.TablePerClassSub2 + com.blazebit.persistence.testsuite.entity.TPCBase + com.blazebit.persistence.testsuite.entity.TPCSub1 + com.blazebit.persistence.testsuite.entity.TPCSub2 com.blazebit.persistence.testsuite.entity.TestAdvancedCTE1 com.blazebit.persistence.testsuite.entity.TestAdvancedCTE2 com.blazebit.persistence.testsuite.entity.TestCTE diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/CollectionJoinTestHibernate.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/CollectionJoinTestHibernate.java index 2078f4c833..29e1647f42 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/CollectionJoinTestHibernate.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/CollectionJoinTestHibernate.java @@ -48,9 +48,9 @@ public void testOneToManyMappedBy() { assertEquals("SELECT indexedNodesMappedBy_0_1, " + joinAliasValue("keyedNodesMappedBy_default_1") + " FROM Root2 r" + " LEFT JOIN r.indexedNodesMappedBy indexedNodesMappedBy_0_1" - + onClause(" (INDEX(indexedNodesMappedBy_0_1) = 0) ") + + onClause("INDEX(indexedNodesMappedBy_0_1) = 0") + " LEFT JOIN r.keyedNodesMappedBy keyedNodesMappedBy_default_1" - + onClause(" (KEY(keyedNodesMappedBy_default_1) = 'default')"), criteria.getQueryString()); + + onClause("KEY(keyedNodesMappedBy_default_1) = 'default'"), criteria.getQueryString()); criteria.getResultList(); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/DeletePolymorphicTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/DeletePolymorphicTest.java index b20f988ab4..9c4bcea4b7 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/DeletePolymorphicTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/DeletePolymorphicTest.java @@ -19,7 +19,6 @@ import com.blazebit.persistence.CriteriaBuilder; import com.blazebit.persistence.DeleteCriteriaBuilder; import com.blazebit.persistence.ReturningResult; -import com.blazebit.persistence.UpdateCriteriaBuilder; import com.blazebit.persistence.testsuite.base.category.NoDatanucleus; import com.blazebit.persistence.testsuite.base.category.NoEclipselink; import com.blazebit.persistence.testsuite.base.category.NoFirebird; @@ -38,9 +37,9 @@ import com.blazebit.persistence.testsuite.entity.PolymorphicSub1; import com.blazebit.persistence.testsuite.entity.PolymorphicSub2; import com.blazebit.persistence.testsuite.entity.StringIdCTE; -import com.blazebit.persistence.testsuite.entity.TablePerClassBase; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub1; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub2; +import com.blazebit.persistence.testsuite.entity.TPCBase; +import com.blazebit.persistence.testsuite.entity.TPCSub2; +import com.blazebit.persistence.testsuite.entity.TPCSub1; import com.blazebit.persistence.testsuite.tx.TxVoidWork; import org.junit.Before; import org.junit.Ignore; @@ -63,8 +62,8 @@ @Ignore("Has to be implemented as part of #345") public class DeletePolymorphicTest extends AbstractCoreTest { - TablePerClassSub1 tpc1; - TablePerClassSub2 tpc2; + TPCSub1 tpc1; + TPCSub2 tpc2; PolymorphicSub1 joined1; PolymorphicSub2 joined2; PolymorphicPropertySub1 st1; @@ -76,9 +75,9 @@ protected Class[] getEntityClasses() { IdHolderCTE.class, StringIdCTE.class, IntIdEntity.class, - TablePerClassBase.class, - TablePerClassSub1.class, - TablePerClassSub2.class, + TPCBase.class, + TPCSub1.class, + TPCSub2.class, PolymorphicBase.class, PolymorphicSub1.class, PolymorphicSub2.class, @@ -95,8 +94,8 @@ public void setUp() { @Override public void work(EntityManager em) { // Table per class data - tpc1 = new TablePerClassSub1(1L, "TPC1"); - tpc2 = new TablePerClassSub2(2L, "TPC2"); + tpc1 = new TPCSub1(1L, "TPC1"); + tpc2 = new TPCSub2(2L, "TPC2"); em.persist(tpc1); em.persist(tpc2); @@ -129,7 +128,7 @@ public void testTablePerClass() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final DeleteCriteriaBuilder cb = cbf.delete(em, TablePerClassBase.class, "t"); + final DeleteCriteriaBuilder cb = cbf.delete(em, TPCBase.class, "t"); cb.where("base").isNotNull(); String expected = "DELETE FROM TablePerClassBase t WHERE t.base IS NOT NULL"; @@ -137,7 +136,7 @@ public void work(EntityManager em) { int updateCount = cb.executeUpdate(); assertEquals(2, updateCount); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } @@ -186,9 +185,9 @@ public void testTablePerClassWithCte() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final DeleteCriteriaBuilder cb = cbf.delete(em, TablePerClassBase.class, "t"); + final DeleteCriteriaBuilder cb = cbf.delete(em, TPCBase.class, "t"); cb.with(IdHolderCTE.class) - .from(TablePerClassBase.class, "t") + .from(TPCBase.class, "t") .bind("id").select("t.id") .end(); cb.where("id").in() @@ -206,7 +205,7 @@ public void work(EntityManager em) { int updateCount = cb.executeUpdate(); assertEquals(2, updateCount); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } @@ -284,7 +283,7 @@ public void testTablePerClassReturning() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final DeleteCriteriaBuilder cb = cbf.delete(em, TablePerClassBase.class, "t"); + final DeleteCriteriaBuilder cb = cbf.delete(em, TPCBase.class, "t"); cb.where("base").isNotNull(); String expected = "DELETE FROM TablePerClassBase t WHERE t.base IS NOT NULL"; @@ -294,7 +293,7 @@ public void work(EntityManager em) { assertEquals(2, returningResult.getUpdateCount()); assertTrue(returningResult.getResultList().contains("TPC1")); assertTrue(returningResult.getResultList().contains("TPC2")); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } @@ -352,7 +351,7 @@ public void testTablePerClassReturningInCTE() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, String.class) .withReturning(StringIdCTE.class) - .delete(TablePerClassBase.class, "t") + .delete(TPCBase.class, "t") .where("base").isNotNull() .returning("id", "base") .end() @@ -370,7 +369,7 @@ public void work(EntityManager em) { assertEquals(2, result.size()); assertTrue(result.contains("TPC1")); assertTrue(result.contains("TPC2")); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } @@ -452,12 +451,12 @@ public void testTablePerClassReturningInCTESelectOld() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, String.class) .withReturning(IdHolderCTE.class) - .delete(TablePerClassBase.class, "t") + .delete(TPCBase.class, "t") .where("base").isNotNull() .returning("id", "id") .end() .from(IdHolderCTE.class, "cte") - .fromOld(TablePerClassBase.class, "t") + .fromOld(TPCBase.class, "t") .where("t.id").eqExpression("cte.id") .select("t.base"); @@ -472,7 +471,7 @@ public void work(EntityManager em) { assertEquals(2, result.size()); assertTrue(result.contains("TPC1")); assertTrue(result.contains("TPC2")); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } @@ -555,11 +554,11 @@ public void testTablePerClassReturningInCTESelectNew() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, Tuple.class) .withReturning(IdHolderCTE.class) - .delete(TablePerClassBase.class, "t") + .delete(TPCBase.class, "t") .where("base").isNotNull() .returning("id", "id") .end() - .fromNew(TablePerClassBase.class, "t") + .fromNew(TPCBase.class, "t") .rightJoinOn(IdHolderCTE.class, "cte") .on("t.id").eqExpression("cte.id") .end() @@ -580,7 +579,7 @@ public void work(EntityManager em) { assertNull(result.get(0).get(1)); assertEquals(tpc2.getId(), result.get(1).get(0)); assertNull(result.get(1).get(1)); - assertTrue(cbf.create(em, TablePerClassBase.class).getResultList().isEmpty()); + assertTrue(cbf.create(em, TPCBase.class).getResultList().isEmpty()); } }); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/OrderByTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/OrderByTest.java index c13edcdcc8..522c398d5c 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/OrderByTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/OrderByTest.java @@ -16,9 +16,11 @@ package com.blazebit.persistence.testsuite; +import static com.googlecode.catchexception.CatchException.verifyException; import static org.junit.Assert.assertEquals; import com.blazebit.persistence.testsuite.base.category.NoDatanucleus; +import com.googlecode.catchexception.CatchException; import org.junit.Assert; import org.junit.Test; @@ -124,11 +126,7 @@ public void testOrderByFunctionCompatibleMode(){ config.setProperty(ConfigurationProperties.COMPATIBLE_MODE, "true"); cbf = config.createCriteriaBuilderFactory(em.getEntityManagerFactory()); CriteriaBuilder criteria = cbf.create(em, Document.class, "d"); - try { - criteria.orderByAsc("SIZE(d.partners)"); - Assert.fail("Expected SyntaxErrorException"); - } catch (SyntaxErrorException ex) { - } + verifyException(criteria, SyntaxErrorException.class).orderByAsc("SIZE(d.partners)"); } @Test diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/SelectPolymorphicTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/SelectPolymorphicTest.java index 2e1172c053..ab1d0f22ca 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/SelectPolymorphicTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/SelectPolymorphicTest.java @@ -22,12 +22,11 @@ import com.blazebit.persistence.testsuite.base.category.NoMySQL; import com.blazebit.persistence.testsuite.base.category.NoOpenJPA; import com.blazebit.persistence.testsuite.entity.IdHolderCTE; -import com.blazebit.persistence.testsuite.entity.TablePerClassBase; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub1; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub2; +import com.blazebit.persistence.testsuite.entity.TPCBase; +import com.blazebit.persistence.testsuite.entity.TPCSub1; +import com.blazebit.persistence.testsuite.entity.TPCSub2; import com.blazebit.persistence.testsuite.tx.TxVoidWork; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -46,9 +45,9 @@ public class SelectPolymorphicTest extends AbstractCoreTest { protected Class[] getEntityClasses() { return new Class[] { IdHolderCTE.class, - TablePerClassBase.class, - TablePerClassSub1.class, - TablePerClassSub2.class + TPCBase.class, + TPCSub1.class, + TPCSub2.class }; } @@ -58,8 +57,8 @@ public void setUpOnce() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - TablePerClassSub1 entity1 = new TablePerClassSub1(1L, "test1"); - TablePerClassSub2 entity2 = new TablePerClassSub2(2L, "test2"); + TPCSub1 entity1 = new TPCSub1(1L, "test1"); + TPCSub2 entity2 = new TPCSub2(2L, "test2"); em.persist(entity1); em.persist(entity2); } @@ -70,9 +69,9 @@ public void work(EntityManager em) { @Test @Category({ NoDatanucleus.class, NoEclipselink.class, NoOpenJPA.class, NoMySQL.class }) public void testSelectTablePerClassWithCte() throws Exception { - CriteriaBuilder cb = cbf.create(em, TablePerClassBase.class, "t") + CriteriaBuilder cb = cbf.create(em, TPCBase.class, "t") .with(IdHolderCTE.class) - .from(TablePerClassBase.class, "t") + .from(TPCBase.class, "t") .bind("id").select("t.id") .end() .where("id").in() @@ -81,15 +80,15 @@ public void testSelectTablePerClassWithCte() throws Exception { .end(); String expected = "WITH IdHolderCTE(id) AS(\n" + - "SELECT t.id FROM TablePerClassBase t\n" + + "SELECT t.id FROM TPCBase t\n" + ")\n" + - "SELECT t FROM TablePerClassBase t WHERE t.id IN (" + + "SELECT t FROM TPCBase t WHERE t.id IN (" + "SELECT cte.id FROM IdHolderCTE cte" + ")"; assertEquals(expected, cb.getQueryString()); - List result = cb.getResultList(); + List result = cb.getResultList(); Assert.assertEquals(2, result.size()); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TablePerClassTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TablePerClassTest.java index a06265e1db..372fa04d7e 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TablePerClassTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TablePerClassTest.java @@ -17,12 +17,11 @@ package com.blazebit.persistence.testsuite; import com.blazebit.persistence.CriteriaBuilder; -import com.blazebit.persistence.testsuite.entity.TablePerClassBase; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub1; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub2; +import com.blazebit.persistence.testsuite.entity.TPCBase; +import com.blazebit.persistence.testsuite.entity.TPCSub1; +import com.blazebit.persistence.testsuite.entity.TPCSub2; import com.blazebit.persistence.testsuite.tx.TxVoidWork; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import javax.persistence.EntityManager; @@ -39,9 +38,9 @@ public class TablePerClassTest extends AbstractCoreTest { @Override protected Class[] getEntityClasses() { return new Class[] { - TablePerClassBase.class, - TablePerClassSub1.class, - TablePerClassSub2.class + TPCBase.class, + TPCSub1.class, + TPCSub2.class }; } @@ -51,8 +50,8 @@ public void setUpOnce() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - TablePerClassSub1 entity1 = new TablePerClassSub1(1L, "test1"); - TablePerClassSub2 entity2 = new TablePerClassSub2(2L, "test2"); + TPCSub1 entity1 = new TPCSub1(1L, "test1"); + TPCSub2 entity2 = new TPCSub2(2L, "test2"); em.persist(entity1); em.persist(entity2); } @@ -61,9 +60,9 @@ public void work(EntityManager em) { @Test public void buildingEntityMetamodelForTablePerClassEntitiesWorks() throws Exception { - CriteriaBuilder cb = cbf.create(em, TablePerClassBase.class); + CriteriaBuilder cb = cbf.create(em, TPCBase.class); - List result = cb.getResultList(); + List result = cb.getResultList(); Assert.assertEquals(2, result.size()); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TreatTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TreatTest.java index 8da70994a7..bd4caf593d 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TreatTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/TreatTest.java @@ -17,13 +17,16 @@ package com.blazebit.persistence.testsuite; import com.blazebit.persistence.CriteriaBuilder; +import com.blazebit.persistence.impl.expression.SyntaxErrorException; import com.blazebit.persistence.testsuite.base.category.NoDatanucleus; import com.blazebit.persistence.testsuite.base.category.NoDatanucleus4; import com.blazebit.persistence.testsuite.base.category.NoEclipselink; import com.blazebit.persistence.testsuite.entity.*; +import com.googlecode.catchexception.CatchException; import org.junit.Test; import org.junit.experimental.categories.Category; +import static com.googlecode.catchexception.CatchException.verifyException; import static org.junit.Assert.assertEquals; /** @@ -44,7 +47,21 @@ protected Class[] getEntityClasses() { } @Test - // NOTE: Apparently a bug in datanucleus? TODO: report the error + public void treatAsExpressionRootNotAllowed() { + CriteriaBuilder criteria = cbf.create(em, Integer.class); + criteria.from(PolymorphicBase.class, "p"); + verifyException(criteria, SyntaxErrorException.class).select("TREAT(p AS PolymorphicSub1)"); + } + + @Test + public void treatOfTreatAsExpressionRootNotAllowed() { + CriteriaBuilder criteria = cbf.create(em, Integer.class); + criteria.from(PolymorphicBase.class, "p"); + verifyException(criteria, SyntaxErrorException.class).select("TREAT(TREAT(p AS PolymorphicSub1).parent1 AS PolymorphicSub1)"); + } + + @Test + // NOTE: Datanucleus does not support root treats properly with joined inheritance. Maybe a bug? TODO: report the error @Category({ NoDatanucleus.class }) public void implicitJoinTreatedRoot() { CriteriaBuilder criteria = cbf.create(em, Integer.class); @@ -55,6 +72,8 @@ public void implicitJoinTreatedRoot() { } @Test + // NOTE: Datanucleus does not support root treats properly with joined inheritance. Maybe a bug? TODO: report the error + @Category({ NoDatanucleus.class }) public void implicitJoinTreatedRelation() { CriteriaBuilder criteria = cbf.create(em, Integer.class); criteria.from(PolymorphicBase.class, "p"); @@ -65,7 +84,21 @@ public void implicitJoinTreatedRelation() { @Test // NOTE: Datanucleus4 reports: We do not currently support JOIN to TREAT - @Category({ NoDatanucleus4.class }) + // NOTE: Datanucleus does not support root treats properly with joined inheritance. Maybe a bug? TODO: report the error + // NOTE: Eclipselink does not support root treat joins i.e. "JOIN TREAT(..).relation" + @Category({ NoDatanucleus.class , NoDatanucleus4.class, NoEclipselink.class }) + public void implicitJoinTreatedRootTreatJoin() { + CriteriaBuilder criteria = cbf.create(em, Integer.class); + criteria.from(PolymorphicBase.class, "p"); + criteria.select("TREAT(TREAT(p AS PolymorphicSub1).parent1 AS PolymorphicSub1).sub1Value"); + assertEquals("SELECT " + treatRoot("parent1_1", PolymorphicSub1.class, "sub1Value") + " FROM PolymorphicBase p LEFT JOIN " + treatRootJoin("p", PolymorphicSub1.class, "parent1") + " parent1_1", criteria.getQueryString()); + criteria.getResultList(); + } + + @Test + // NOTE: Datanucleus4 reports: We do not currently support JOIN to TREAT + // NOTE: Datanucleus does not support root treats properly with joined inheritance. Maybe a bug? TODO: report the error + @Category({ NoDatanucleus.class, NoDatanucleus4.class }) public void joinTreatedRelation() { CriteriaBuilder criteria = cbf.create(em, Integer.class); criteria.from(PolymorphicBase.class, "p"); @@ -76,9 +109,8 @@ public void joinTreatedRelation() { } @Test - // TODO: This is an extension of the treat grammar. Maybe we should render a cross/left join for the root path treat and then just treat on the other alias? - // NOTE: Apparently a bug in datanucleus? TODO: report the error - // Eclipselink does not support dereferencing of TREAT join path elements + // NOTE: With datanucleus this only fails with INNER JOIN but works with left join. Maybe a bug? TODO: report the error + // Eclipselink and Datanucleus do not support root treat joins @Category({ NoDatanucleus.class, NoEclipselink.class}) public void joinTreatedRoot() { CriteriaBuilder criteria = cbf.create(em, Integer.class); @@ -90,8 +122,7 @@ public void joinTreatedRoot() { } @Test - // TODO: This is an extension of the treat grammar. Maybe we should render a cross/left join for the root path treat and then just treat on the other alias? - // NOTE: Apparently a bug in datanucleus? TODO: report the error + // NOTE: With datanucleus this only fails with INNER JOIN but works with left join. Maybe a bug? TODO: report the error // Eclipselink does not support dereferencing of TREAT join path elements @Category({ NoDatanucleus.class, NoEclipselink.class }) public void joinTreatedRootEmbeddable() { @@ -104,8 +135,7 @@ public void joinTreatedRootEmbeddable() { } @Test - // TODO: This is an extension of the treat grammar. Maybe we should render a cross/left join for the root path treat and then just treat on the other alias? - // NOTE: Apparently a bug in datanucleus? TODO: report the error + // NOTE: With datanucleus this only fails with INNER JOIN but works with left join. Maybe a bug? TODO: report the error // Eclipselink does not support dereferencing of TREAT join path elements @Category({ NoDatanucleus.class, NoEclipselink.class }) public void selectTreatedRootEmbeddable() { @@ -117,8 +147,7 @@ public void selectTreatedRootEmbeddable() { } @Test - // TODO: This is an extension of the treat grammar. Maybe we should render a cross/left join for the root path treat and then just treat on the other alias? - // NOTE: Apparently a bug in datanucleus? TODO: report the error + // NOTE: With datanucleus this only fails with INNER JOIN but works with left join. Maybe a bug? TODO: report the error @Category({ NoDatanucleus.class }) public void treatJoinTreatedRootRelation() { CriteriaBuilder criteria = cbf.create(em, Integer.class); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/UpdatePolymorphicTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/UpdatePolymorphicTest.java index ca8ad4b6fb..1ae7f51503 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/UpdatePolymorphicTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/UpdatePolymorphicTest.java @@ -37,9 +37,9 @@ import com.blazebit.persistence.testsuite.entity.PolymorphicSub1; import com.blazebit.persistence.testsuite.entity.PolymorphicSub2; import com.blazebit.persistence.testsuite.entity.StringIdCTE; -import com.blazebit.persistence.testsuite.entity.TablePerClassBase; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub1; -import com.blazebit.persistence.testsuite.entity.TablePerClassSub2; +import com.blazebit.persistence.testsuite.entity.TPCBase; +import com.blazebit.persistence.testsuite.entity.TPCSub1; +import com.blazebit.persistence.testsuite.entity.TPCSub2; import com.blazebit.persistence.testsuite.tx.TxVoidWork; import org.junit.Before; import org.junit.Ignore; @@ -67,9 +67,9 @@ protected Class[] getEntityClasses() { IdHolderCTE.class, StringIdCTE.class, IntIdEntity.class, - TablePerClassBase.class, - TablePerClassSub1.class, - TablePerClassSub2.class, + TPCBase.class, + TPCSub1.class, + TPCSub2.class, PolymorphicBase.class, PolymorphicSub1.class, PolymorphicSub2.class, @@ -86,8 +86,8 @@ public void setUp() { @Override public void work(EntityManager em) { // Table per class data - TablePerClassSub1 tpc1 = new TablePerClassSub1(1L, "TPC1"); - TablePerClassSub2 tpc2 = new TablePerClassSub2(2L, "TPC2"); + TPCSub1 tpc1 = new TPCSub1(1L, "TPC1"); + TPCSub2 tpc2 = new TPCSub2(2L, "TPC2"); em.persist(tpc1); em.persist(tpc2); @@ -120,7 +120,7 @@ public void testTablePerClass() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final UpdateCriteriaBuilder cb = cbf.update(em, TablePerClassBase.class, "t"); + final UpdateCriteriaBuilder cb = cbf.update(em, TPCBase.class, "t"); cb.setExpression("base", "CONCAT(base, ' - 1')"); String expected = "UPDATE TablePerClassBase t SET t.base = CONCAT(base,' - 1')"; @@ -174,9 +174,9 @@ public void testTablePerClassWithCte() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final UpdateCriteriaBuilder cb = cbf.update(em, TablePerClassBase.class, "t"); + final UpdateCriteriaBuilder cb = cbf.update(em, TPCBase.class, "t"); cb.with(IdHolderCTE.class) - .from(TablePerClassBase.class, "t") + .from(TPCBase.class, "t") .bind("id").select("t.id") .end(); cb.where("id").in() @@ -272,7 +272,7 @@ public void testTablePerClassReturning() { transactional(new TxVoidWork() { @Override public void work(EntityManager em) { - final UpdateCriteriaBuilder cb = cbf.update(em, TablePerClassBase.class, "t"); + final UpdateCriteriaBuilder cb = cbf.update(em, TPCBase.class, "t"); cb.setExpression("base", "CONCAT(base, ' - 1')"); String expected = "UPDATE TablePerClassBase t SET t.base = CONCAT(base,' - 1')"; @@ -337,7 +337,7 @@ public void testTablePerClassReturningInCTE() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, String.class) .withReturning(StringIdCTE.class) - .update(TablePerClassBase.class, "t") + .update(TPCBase.class, "t") .setExpression("base", "CONCAT(base, ' - 1')") .returning("id", "base") .end() @@ -434,12 +434,12 @@ public void testTablePerClassReturningInCTESelectOld() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, String.class) .withReturning(IdHolderCTE.class) - .update(TablePerClassBase.class, "t") + .update(TPCBase.class, "t") .setExpression("base", "CONCAT(base, ' - 1')") .returning("id", "id") .end() .from(IdHolderCTE.class, "cte") - .fromOld(TablePerClassBase.class, "t") + .fromOld(TPCBase.class, "t") .where("t.id").eqExpression("cte.id") .select("t.base"); @@ -535,12 +535,12 @@ public void testTablePerClassReturningInCTESelectNew() { public void work(EntityManager em) { final CriteriaBuilder cb = cbf.create(em, String.class) .withReturning(IdHolderCTE.class) - .update(TablePerClassBase.class, "t") + .update(TPCBase.class, "t") .setExpression("base", "CONCAT(base, ' - 1')") .returning("id", "id") .end() .from(IdHolderCTE.class, "cte") - .fromNew(TablePerClassBase.class, "t") + .fromNew(TPCBase.class, "t") .where("t.id").eqExpression("cte.id") .select("t.base"); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/AbstractTreatVariationsTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/AbstractTreatVariationsTest.java index 65fa27897c..3dd9401f30 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/AbstractTreatVariationsTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/AbstractTreatVariationsTest.java @@ -19,31 +19,31 @@ import com.blazebit.persistence.CriteriaBuilder; import com.blazebit.persistence.testsuite.AbstractCoreTest; -import com.blazebit.persistence.testsuite.base.category.NoDatanucleus; -import com.blazebit.persistence.testsuite.base.category.NoEclipselink; -import com.blazebit.persistence.testsuite.base.category.NoHibernate; -import com.blazebit.persistence.testsuite.base.category.NoOpenJPA; import com.blazebit.persistence.testsuite.treat.entity.Base; import com.blazebit.persistence.testsuite.treat.entity.BaseEmbeddable; import com.blazebit.persistence.testsuite.treat.entity.IntIdEntity; +import com.blazebit.persistence.testsuite.treat.entity.JoinedBase; import com.blazebit.persistence.testsuite.treat.entity.JoinedSub1; import com.blazebit.persistence.testsuite.treat.entity.JoinedSub2; +import com.blazebit.persistence.testsuite.treat.entity.SingleTableBase; import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub1; import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub2; import com.blazebit.persistence.testsuite.treat.entity.Sub1; import com.blazebit.persistence.testsuite.treat.entity.Sub1Embeddable; import com.blazebit.persistence.testsuite.treat.entity.Sub2; import com.blazebit.persistence.testsuite.treat.entity.Sub2Embeddable; +import com.blazebit.persistence.testsuite.treat.entity.TablePerClassBase; import com.blazebit.persistence.testsuite.treat.entity.TablePerClassSub1; import com.blazebit.persistence.testsuite.treat.entity.TablePerClassSub2; import com.blazebit.persistence.testsuite.tx.TxVoidWork; import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; import org.junit.FixMethodOrder; -import org.junit.experimental.categories.Category; import org.junit.runners.MethodSorters; import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; +import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -63,17 +63,17 @@ public AbstractTreatVariationsTest(String strategy, String objectPrefix) { @Override protected Class[] getEntityClasses() { return new Class[] { - Base.class, BaseEmbeddable.class, IntIdEntity.class, + JoinedBase.class, JoinedSub1.class, JoinedSub2.class, + SingleTableBase.class, SingleTableSub1.class, SingleTableSub2.class, - Sub1.class, Sub1Embeddable.class, - Sub2.class, Sub2Embeddable.class, + TablePerClassBase.class, TablePerClassSub1.class, TablePerClassSub2.class }; @@ -109,7 +109,9 @@ public void work(EntityManager em) { JoinedSub1 s1Parent = new JoinedSub1("s1.parent"); JoinedSub2 s2Parent = new JoinedSub2("s2.parent"); - persist(em, i1, s1, s2, s1Parent, s2Parent); + if (strategy.equals("Joined") && supportsJoinedInheritance()) { + persist(em, i1, s1, s2, s1Parent, s2Parent); + } /**************** * Single Table @@ -120,7 +122,9 @@ public void work(EntityManager em) { SingleTableSub1 st1Parent = new SingleTableSub1("st1.parent"); SingleTableSub2 st2Parent = new SingleTableSub2("st2.parent"); - persist(em, i1, st1, st2, st1Parent, st2Parent); + if (strategy.equals("SingleTable")) { + persist(em, i1, st1, st2, st1Parent, st2Parent); + } /**************** * Table per Class @@ -133,11 +137,20 @@ public void work(EntityManager em) { // The Java compiler can't up-cast automatically, maybe a bug? //persist(em, i1, tpc1, tpc2, tpc1Parent, tpc2Parent); - persist(em, i1, (Sub1) tpc1, (Sub2) tpc2, (Sub1) tpc1Parent, (Sub2) tpc2Parent); + if (strategy.equals("TablePerClass") && supportsTablePerClassInheritance()) { + persist(em, i1, (Sub1) tpc1, (Sub2) tpc2, (Sub1) tpc1Parent, (Sub2) tpc2Parent); + } } }); } + @Before + public void generalAssumptions() { + assumeTablePerClassSupportedWithTreat(); + assumeJoinedSupportedWithTreat(); + } + + @SuppressWarnings("unchecked") private void persist( EntityManager em, IntIdEntity i1, @@ -240,7 +253,8 @@ protected List list(CriteriaBuilder cb) { em.getTransaction().rollback(); em.close(); emf.close(); - return bases; + // Return new list since datanucleus makes it impossible to modify the direct result + return new ArrayList<>(bases); } protected void assertRemoved(List list, Object[] expected) { @@ -262,5 +276,83 @@ protected void assertRemoved(List list, Object expected) { Assert.fail(list + " does not contain expected entry: " + expected); } + + protected void assumeQueryLanguageSupportsKeyDeReference() { + Assume.assumeTrue("The JPA provider does not support de-referencing map keys", supportsMapKeyDeReference()); + } + + protected void assumeHibernateSupportsMultiTpcWithTypeExpression() { + // TODO: create issue for this + Assume.assumeFalse("Hibernate does not prefix the table per class discriminator column properly when using a type expression!", strategy.equals("TablePerClass")); + } + + protected void assumeInverseSetCorrelationJoinsSubtypesWhenJoined() { + Assume.assumeTrue("Hibernate before 5 did not support joining an inverse collection that has a joined inheritance type!", strategy.equals("Joined") && supportsInverseSetCorrelationJoinsSubtypesWhenJoined()); + } + + protected void assumeRootTreatJoinSupportedOrEmulated() { + Assume.assumeTrue("The JPA provider does not support root treat joins!", jpaProvider.supportsRootTreatJoin() || jpaProvider.supportsSubtypeRelationResolving()); + } + + protected void assumeTreatJoinWithRootTreatSupportedOrEmulated() { + Assume.assumeTrue("The JPA provider does not support a treat join that contains a root treat!", jpaProvider.supportsRootTreatTreatJoin() || jpaProvider.supportsSubtypeRelationResolving()); + } + + protected void assumeCollectionTreatJoinWithRootTreatWorks() { + Assume.assumeTrue("Eclipselink does not support a treat join of a collection when containing a root treat!", !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeAccessTreatedOuterQueryVariableWorks() { + Assume.assumeTrue("Eclipselink does not support using a treat in a subquery referring to the outer query!", !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeTreatInSubqueryCorrelationWorks() { + Assume.assumeTrue("The JPA provider does not support treat as correlation path in a subquery!", jpaProvider.supportsTreatCorrelation() || jpaProvider.supportsSubtypeRelationResolving()); + } + + protected void assumeMapInEmbeddableIsSupported() { + Assume.assumeTrue("Only Hibernate supports mapping a java.util.Map in an embeddable!", jpaProvider.getClass().getName().contains("Hibernate")); + } + + protected void assumeTreatMapAssociationIsSupported() { + // Seems the code assumes it's the "key" of the map when it's actually a "treat" + Assume.assumeTrue("Eclipselink does not support treating an association of type java.util.Map!", !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeMultipleTreatJoinWithSingleTableIsNotBroken() { + // So with Eclipselink having two different treat joins that use the same join path will result in a single sql join. Type restrictions are in the WHERE clause + Assume.assumeTrue("Eclipselink does not support multiple treat joins on the same relation with single table inheritance!", !strategy.equals("SingleTable") || !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeLeftTreatJoinWithSingleTableIsNotBroken() { + // Eclipselink puts the type restriction of a left treat join in the WHERE clause which is wrong. The type restriction should be part of the ON clause + Assume.assumeTrue("Eclipselink does not support left treat joins with single table inheritance properly as the type filter is not part of the join condition!", !strategy.equals("SingleTable") || !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeLeftTreatJoinWithRootTreatIsNotBroken() { + // Eclipselink puts the type restriction of a left treat join in the WHERE clause which is wrong. The type restriction should be part of the ON clause + Assume.assumeTrue("Eclipselink does not support left treat joins with root treats properly as the type filter is not part of the join condition!", !jpaProvider.getClass().getName().contains("Eclipse")); + } + + protected void assumeTreatInNonPredicateDoesNotFilter() { + // Eclipselink creates type restrictions for every treat expression it encounters, regardless of the location + Assume.assumeTrue("Eclipelink does not support treat in non-predicates without filtering the result!", !jpaProvider.getClass().getName().contains("Eclipse")); + } + + private boolean supportsTablePerClassInheritance() { + return !jpaProvider.getClass().getName().contains("Eclipse"); + } + + private void assumeTablePerClassSupportedWithTreat() { + Assume.assumeTrue("Eclipselink does not support treat when using the table per class strategy!", !strategy.equals("TablePerClass") || supportsTablePerClassInheritance()); + } + + private boolean supportsJoinedInheritance() { + return !jpaProvider.getClass().getName().contains("DataNucleus"); + } + + private void assumeJoinedSupportedWithTreat() { + Assume.assumeTrue("Datanucleus does not support treat when using the joined strategy!", !strategy.equals("Joined") || supportsJoinedInheritance()); + } } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapKeyTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapKeyTest.java deleted file mode 100644 index 33b3dde574..0000000000 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapKeyTest.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright 2014 - 2017 Blazebit. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.blazebit.persistence.testsuite.treat.builder; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.util.List; - -@RunWith(Parameterized.class) -public class JoinManyToManyMapKeyTest extends AbstractTreatVariationsTest { - - public JoinManyToManyMapKeyTest(String strategy, String objectPrefix) { - super(strategy, objectPrefix); - } - - @Parameterized.Parameters - public static Object[] getParameters() { - return new Object[] { - new Object[] { "Joined", "s" }, - new Object[] { "SingleTable", "st" }, - new Object[] { "TablePerClass", "tpc" } - }; - } - - @Test - public void treatJoinManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("TREAT(KEY(b.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - ); - System.out.println("treatJoinManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("TREAT(KEY(b.map) AS " + strategy + "Sub1)", "s1") - .leftJoin("TREAT(KEY(b.map) AS " + strategy + "Sub2)", "s2") - .select("s1.sub1Value") - .select("s2.sub2Value") - ); - System.out.println("treatJoinMultipleManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map) => 4 instances - // Left join on KEY(b.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinParentManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(b.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - ); - System.out.println("treatJoinParentManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys but only two are Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleParentManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(b.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - .selectSubquery() - .from("TREAT(KEY(b.map) AS " + strategy + "Sub2)", "s2") - .select("s2.sub2Value") - .end() - ); - System.out.println("treatJoinMultipleParentManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys, two are Sub1 and the other are Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - ); - System.out.println("treatJoinEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1)", "s1") - .leftJoin("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2)", "s2") - .select("s1.sub1Value") - .select("s2.sub2Value") - ); - System.out.println("treatJoinMultipleEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinParentEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - ); - System.out.println("treatJoinParentEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys but only two are Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleParentEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - .selectSubquery() - .from("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2)", "s2") - .select("s2.sub2Value") - .end() - ); - System.out.println("treatJoinMultipleParentEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys, two are Sub1 and the other are Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedRootManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub1).map1)", "s1") - .select("s1.value") - ); - System.out.println("joinTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedRootManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub1).map1)", "s1") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub2).map2)", "s2") - .select("s1.value") - .select("s2.value") - ); - System.out.println("joinMultipleTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - // Left join on KEY(b.map2) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedParentRootManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub1).map1)", "s1") - .select("s1.value") - .end() - ); - System.out.println("joinTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedParentRootManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub1).map1)", "s1") - .select("s1.value") - .end() - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub1).map2)", "s2") - .select("s2.value") - .end() - ); - System.out.println("joinMultipleTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map)", "s1") - .select("s1.value") - ); - System.out.println("joinTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on b.embeddable.sub1Parent => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map)", "s1") - .leftJoin("KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map)", "s2") - .select("s1.value") - .select("s2.value") - ); - System.out.println("joinMultipleTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - // Left join on KEY(b.embeddable2.sub2Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedParentRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map)", "s1") - .select("s1.value") - .end() - ); - System.out.println("joinTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedParentRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map)", "s1") - .select("s1.value") - .end() - .selectSubquery() - .from("KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map)", "s2") - .select("s2.value") - .end() - ); - System.out.println("joinMultipleTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedRootManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - ); - System.out.println("treatJoinTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedRootManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1)", "s1") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2)", "s2") - .select("s1.sub1Value") - .select("s2.sub2Value") - ); - System.out.println("treatJoinMultipleTreatedRooManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - // Left join on KEY(b.map2) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedParentRootManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - ); - System.out.println("treatJoinTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedParentRootManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2)", "s2") - .select("s2.sub2Value") - .end() - ); - System.out.println("treatJoinMultipleTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - ); - System.out.println("treatJoinTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1)", "s1") - .leftJoin("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2)", "s2") - .select("s1.sub1Value") - .select("s2.sub2Value") - ); - System.out.println("treatJoinMultipleTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - // Left join on KEY(b.embeddable2.sub2Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedParentRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Integer.class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - ); - System.out.println("treatJoinTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapKey() { - List bases = list( - from(Object[].class, "Base", "b") - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1)", "s1") - .select("s1.sub1Value") - .end() - .selectSubquery() - .from("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2)", "s2") - .select("s2.sub2Value") - .end() - ); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - -} diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapValueTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapValueTest.java index 2a9d40112a..3747aad82e 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapValueTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToManyMapValueTest.java @@ -41,13 +41,13 @@ public static Object[] getParameters() { @Test public void treatJoinManyToManyMapValue() { + assumeTreatMapAssociationIsSupported(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.map AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,6 +59,7 @@ public void treatJoinManyToManyMapValue() { @Test public void treatJoinMultipleManyToManyMapValue() { + assumeTreatMapAssociationIsSupported(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.map AS " + strategy + "Sub1)", "s1") @@ -66,8 +67,7 @@ public void treatJoinMultipleManyToManyMapValue() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map => 4 instances // Left join on b.map => 4 instances @@ -80,6 +80,7 @@ public void treatJoinMultipleManyToManyMapValue() { @Test public void treatJoinParentManyToManyMapValue() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -87,8 +88,7 @@ public void treatJoinParentManyToManyMapValue() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values but only two are Sub1 Assert.assertEquals(4, bases.size()); @@ -100,6 +100,7 @@ public void treatJoinParentManyToManyMapValue() { @Test public void treatJoinMultipleParentManyToManyMapValue() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -111,8 +112,7 @@ public void treatJoinMultipleParentManyToManyMapValue() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values, two are Sub1 and the other are Sub2 Assert.assertEquals(4, bases.size()); @@ -124,13 +124,13 @@ public void treatJoinMultipleParentManyToManyMapValue() { @Test public void treatJoinEmbeddableManyToManyMapValue() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.embeddable.map AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -142,6 +142,7 @@ public void treatJoinEmbeddableManyToManyMapValue() { @Test public void treatJoinMultipleEmbeddableManyToManyMapValue() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.embeddable.map AS " + strategy + "Sub1)", "s1") @@ -149,8 +150,7 @@ public void treatJoinMultipleEmbeddableManyToManyMapValue() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances // Left join on b.embeddable.map => 4 instances @@ -163,6 +163,8 @@ public void treatJoinMultipleEmbeddableManyToManyMapValue() { @Test public void treatJoinParentEmbeddableManyToManyMapValue() { + assumeTreatInSubqueryCorrelationWorks(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -170,8 +172,7 @@ public void treatJoinParentEmbeddableManyToManyMapValue() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values but only two are Sub1 Assert.assertEquals(4, bases.size()); @@ -183,6 +184,8 @@ public void treatJoinParentEmbeddableManyToManyMapValue() { @Test public void treatJoinMultipleParentEmbeddableManyToManyMapValue() { + assumeTreatInSubqueryCorrelationWorks(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -194,8 +197,7 @@ public void treatJoinMultipleParentEmbeddableManyToManyMapValue() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values, two are Sub1 and the other are Sub2 Assert.assertEquals(4, bases.size()); @@ -208,25 +210,28 @@ public void treatJoinMultipleParentEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).map1", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).map1", "s1") @@ -234,14 +239,13 @@ public void joinMultipleTreatedRootManyToManyMapValue() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 => 4 instances // Left join on b.map2 => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -249,6 +253,7 @@ public void joinMultipleTreatedRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -256,20 +261,20 @@ public void joinTreatedParentRootManyToManyMapValue() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances - // There are two map values but only one is Sub1 + // There are two map values Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -277,17 +282,16 @@ public void joinMultipleTreatedParentRootManyToManyMapValue() { .select("s1.value") .end() .selectSubquery() - .from("TREAT(b AS " + strategy + "Sub1).map2", "s2") + .from("TREAT(b AS " + strategy + "Sub2).map2", "s2") .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -295,25 +299,28 @@ public void joinMultipleTreatedParentRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map", "s1") @@ -321,14 +328,13 @@ public void joinMultipleTreatedRootEmbeddableManyToManyMapValue() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances // Left join on b.embeddable2.sub2Parent => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -336,6 +342,7 @@ public void joinMultipleTreatedRootEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -343,20 +350,20 @@ public void joinTreatedParentRootEmbeddableManyToManyMapValue() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances - // There are two map values but only one is Sub1 + // There are two map values Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -368,13 +375,12 @@ public void joinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances - // There are two map values, one is Sub1 and the other Sub2 + // There are four map values, two Sub1 and two Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -382,13 +388,14 @@ public void joinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).map1 AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -401,6 +408,8 @@ public void treatJoinTreatedRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).map1 AS " + strategy + "Sub1)", "s1") @@ -408,8 +417,7 @@ public void treatJoinMultipleTreatedRootManyToManyMapValue() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 => 4 instances // Left join on b.map2 => 4 instances @@ -423,6 +431,8 @@ public void treatJoinMultipleTreatedRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -430,8 +440,7 @@ public void treatJoinTreatedParentRootManyToManyMapValue() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -444,6 +453,8 @@ public void treatJoinTreatedParentRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -455,8 +466,7 @@ public void treatJoinMultipleTreatedParentRootManyToManyMapValue() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -469,13 +479,14 @@ public void treatJoinMultipleTreatedParentRootManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootEmbeddableManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -488,6 +499,8 @@ public void treatJoinTreatedRootEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootEmbeddableManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1)", "s1") @@ -495,8 +508,7 @@ public void treatJoinMultipleTreatedRootEmbeddableManyToManyMapValue() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances // Left join on b.embeddable2.sub2Parent => 4 instances @@ -510,6 +522,8 @@ public void treatJoinMultipleTreatedRootEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootEmbeddableManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -517,8 +531,7 @@ public void treatJoinTreatedParentRootEmbeddableManyToManyMapValue() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -531,6 +544,8 @@ public void treatJoinTreatedParentRootEmbeddableManyToManyMapValue() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -542,8 +557,7 @@ public void treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToOneTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToOneTest.java index 8f0f4cd19d..bdd5ab8c83 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToOneTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinManyToOneTest.java @@ -41,13 +41,13 @@ public static Object[] getParameters() { @Test public void treatJoinManyToOne() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.parent AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,6 +59,8 @@ public void treatJoinManyToOne() { @Test public void treatJoinMultipleManyToOne() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.parent AS " + strategy + "Sub1)", "s1") @@ -66,8 +68,7 @@ public void treatJoinMultipleManyToOne() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances // Left join on b.parent => 4 instances @@ -80,6 +81,7 @@ public void treatJoinMultipleManyToOne() { @Test public void treatJoinParentManyToOne() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -87,8 +89,7 @@ public void treatJoinParentManyToOne() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -100,6 +101,7 @@ public void treatJoinParentManyToOne() { @Test public void treatJoinMultipleParentManyToOne() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -111,8 +113,7 @@ public void treatJoinMultipleParentManyToOne() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -124,13 +125,13 @@ public void treatJoinMultipleParentManyToOne() { @Test public void treatJoinEmbeddableManyToOne() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.embeddable.parent AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -142,6 +143,8 @@ public void treatJoinEmbeddableManyToOne() { @Test public void treatJoinMultipleEmbeddableManyToOne() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.embeddable.parent AS " + strategy + "Sub1)", "s1") @@ -149,8 +152,7 @@ public void treatJoinMultipleEmbeddableManyToOne() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable.parent => 4 instances // Left join on b.embeddable.parent => 4 instances @@ -163,6 +165,7 @@ public void treatJoinMultipleEmbeddableManyToOne() { @Test public void treatJoinParentEmbeddableManyToOne() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -170,8 +173,7 @@ public void treatJoinParentEmbeddableManyToOne() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -183,6 +185,7 @@ public void treatJoinParentEmbeddableManyToOne() { @Test public void treatJoinMultipleParentEmbeddableManyToOne() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -194,8 +197,7 @@ public void treatJoinMultipleParentEmbeddableManyToOne() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -208,13 +210,14 @@ public void treatJoinMultipleParentEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).parent1", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,6 +230,8 @@ public void joinTreatedRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).parent1", "s1") @@ -234,8 +239,7 @@ public void joinMultipleTreatedRootManyToOne() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 => 4 instances // Left join on b.parent2 => 4 instances @@ -249,6 +253,7 @@ public void joinMultipleTreatedRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -256,8 +261,7 @@ public void joinTreatedParentRootManyToOne() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -270,6 +274,7 @@ public void joinTreatedParentRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -277,12 +282,11 @@ public void joinMultipleTreatedParentRootManyToOne() { .select("s1.value") .end() .selectSubquery() - .from("TREAT(b AS " + strategy + "Sub1).parent2", "s2") + .from("TREAT(b AS " + strategy + "Sub2).parent2", "s2") .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -295,13 +299,14 @@ public void joinMultipleTreatedParentRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -314,6 +319,8 @@ public void joinTreatedRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent", "s1") @@ -321,8 +328,7 @@ public void joinMultipleTreatedRootEmbeddableManyToOne() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances // Left join on b.embeddable2.sub2Parent => 4 instances @@ -336,6 +342,7 @@ public void joinMultipleTreatedRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -343,8 +350,7 @@ public void joinTreatedParentRootEmbeddableManyToOne() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -357,6 +363,7 @@ public void joinTreatedParentRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -368,8 +375,7 @@ public void joinMultipleTreatedParentRootEmbeddableManyToOne() { .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -382,13 +388,14 @@ public void joinMultipleTreatedParentRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeLeftTreatJoinWithRootTreatIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).parent1 AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -401,6 +408,8 @@ public void treatJoinTreatedRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeLeftTreatJoinWithRootTreatIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).parent1 AS " + strategy + "Sub1)", "s1") @@ -408,8 +417,7 @@ public void treatJoinMultipleTreatedRootManyToOne() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 => 4 instances // Left join on b.parent2 => 4 instances @@ -423,6 +431,8 @@ public void treatJoinMultipleTreatedRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -430,8 +440,7 @@ public void treatJoinTreatedParentRootManyToOne() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -444,6 +453,8 @@ public void treatJoinTreatedParentRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -455,8 +466,7 @@ public void treatJoinMultipleTreatedParentRootManyToOne() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -469,13 +479,14 @@ public void treatJoinMultipleTreatedParentRootManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootEmbeddableManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeLeftTreatJoinWithRootTreatIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -488,6 +499,8 @@ public void treatJoinTreatedRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootEmbeddableManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeLeftTreatJoinWithRootTreatIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1)", "s1") @@ -495,8 +508,7 @@ public void treatJoinMultipleTreatedRootEmbeddableManyToOne() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances // Left join on b.embeddable2.sub2Parent => 4 instances @@ -510,6 +522,8 @@ public void treatJoinMultipleTreatedRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootEmbeddableManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -517,8 +531,7 @@ public void treatJoinTreatedParentRootEmbeddableManyToOne() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -531,6 +544,8 @@ public void treatJoinTreatedParentRootEmbeddableManyToOne() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootEmbeddableManyToOne() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -542,8 +557,7 @@ public void treatJoinMultipleTreatedParentRootEmbeddableManyToOne() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyInverseSetTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyInverseSetTest.java index cd6ba9ec41..644ee6a877 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyInverseSetTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyInverseSetTest.java @@ -41,13 +41,13 @@ public static Object[] getParameters() { @Test public void treatJoinOneToManyInverseSet() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.children AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,6 +59,8 @@ public void treatJoinOneToManyInverseSet() { @Test public void treatJoinMultipleOneToManyInverseSet() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.children AS " + strategy + "Sub1)", "s1") @@ -66,8 +68,7 @@ public void treatJoinMultipleOneToManyInverseSet() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances // Left join on b.children => 4 instances @@ -80,6 +81,8 @@ public void treatJoinMultipleOneToManyInverseSet() { @Test public void treatJoinParentOneToManyInverseSet() { + assumeTreatInSubqueryCorrelationWorks(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -87,8 +90,7 @@ public void treatJoinParentOneToManyInverseSet() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -100,6 +102,8 @@ public void treatJoinParentOneToManyInverseSet() { @Test public void treatJoinMultipleParentOneToManyInverseSet() { + assumeTreatInSubqueryCorrelationWorks(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -111,8 +115,7 @@ public void treatJoinMultipleParentOneToManyInverseSet() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -124,13 +127,13 @@ public void treatJoinMultipleParentOneToManyInverseSet() { @Test public void treatJoinEmbeddableOneToManyInverseSet() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.embeddable.children AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -142,6 +145,8 @@ public void treatJoinEmbeddableOneToManyInverseSet() { @Test public void treatJoinMultipleEmbeddableOneToManyInverseSet() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.embeddable.children AS " + strategy + "Sub1)", "s1") @@ -149,8 +154,7 @@ public void treatJoinMultipleEmbeddableOneToManyInverseSet() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable.children => 4 instances // Left join on b.embeddable.children => 4 instances @@ -163,6 +167,8 @@ public void treatJoinMultipleEmbeddableOneToManyInverseSet() { @Test public void treatJoinParentEmbeddableOneToManyInverseSet() { + assumeTreatInSubqueryCorrelationWorks(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -170,8 +176,7 @@ public void treatJoinParentEmbeddableOneToManyInverseSet() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -183,6 +188,8 @@ public void treatJoinParentEmbeddableOneToManyInverseSet() { @Test public void treatJoinMultipleParentEmbeddableOneToManyInverseSet() { + assumeTreatInSubqueryCorrelationWorks(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -194,8 +201,7 @@ public void treatJoinMultipleParentEmbeddableOneToManyInverseSet() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -208,13 +214,13 @@ public void treatJoinMultipleParentEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).children1", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,6 +233,7 @@ public void joinTreatedRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).children1", "s1") @@ -234,8 +241,7 @@ public void joinMultipleTreatedRootOneToManyInverseSet() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 => 4 instances // Left join on b.children2 => 4 instances @@ -249,6 +255,8 @@ public void joinMultipleTreatedRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -256,8 +264,7 @@ public void joinTreatedParentRootOneToManyInverseSet() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -270,6 +277,8 @@ public void joinTreatedParentRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -277,12 +286,11 @@ public void joinMultipleTreatedParentRootOneToManyInverseSet() { .select("s1.value") .end() .selectSubquery() - .from("TREAT(b AS " + strategy + "Sub1).children2", "s2") + .from("TREAT(b AS " + strategy + "Sub2).children2", "s2") .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -295,13 +303,13 @@ public void joinMultipleTreatedParentRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances Assert.assertEquals(4, bases.size()); @@ -314,6 +322,7 @@ public void joinTreatedRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children", "s1") @@ -321,8 +330,7 @@ public void joinMultipleTreatedRootEmbeddableOneToManyInverseSet() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances // Left join on b.embeddable2.sub2Children => 4 instances @@ -336,6 +344,8 @@ public void joinMultipleTreatedRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -343,8 +353,7 @@ public void joinTreatedParentRootEmbeddableOneToManyInverseSet() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -357,6 +366,8 @@ public void joinTreatedParentRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeInverseSetCorrelationJoinsSubtypesWhenJoined(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -368,8 +379,7 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -382,13 +392,14 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).children1 AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -401,6 +412,8 @@ public void treatJoinTreatedRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).children1 AS " + strategy + "Sub1)", "s1") @@ -408,8 +421,7 @@ public void treatJoinMultipleTreatedRootOneToManyInverseSet() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 => 4 instances // Left join on b.children2 => 4 instances @@ -423,6 +435,8 @@ public void treatJoinMultipleTreatedRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -430,8 +444,7 @@ public void treatJoinTreatedParentRootOneToManyInverseSet() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -444,6 +457,8 @@ public void treatJoinTreatedParentRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -455,8 +470,7 @@ public void treatJoinMultipleTreatedParentRootOneToManyInverseSet() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -469,13 +483,14 @@ public void treatJoinMultipleTreatedParentRootOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootEmbeddableOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances Assert.assertEquals(4, bases.size()); @@ -488,6 +503,8 @@ public void treatJoinTreatedRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootEmbeddableOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1)", "s1") @@ -495,8 +512,7 @@ public void treatJoinMultipleTreatedRootEmbeddableOneToManyInverseSet() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances // Left join on b.embeddable2.sub2Children => 4 instances @@ -510,6 +526,8 @@ public void treatJoinMultipleTreatedRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -517,8 +535,7 @@ public void treatJoinTreatedParentRootEmbeddableOneToManyInverseSet() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -531,6 +548,8 @@ public void treatJoinTreatedParentRootEmbeddableOneToManyInverseSet() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -542,8 +561,7 @@ public void treatJoinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyListTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyListTest.java index eddded23c4..724259ee1a 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyListTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/JoinOneToManyListTest.java @@ -41,13 +41,13 @@ public static Object[] getParameters() { @Test public void treatJoinOneToManyList() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.list AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,6 +59,8 @@ public void treatJoinOneToManyList() { @Test public void treatJoinMultipleOneToManyList() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.list AS " + strategy + "Sub1)", "s1") @@ -66,8 +68,7 @@ public void treatJoinMultipleOneToManyList() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances // Left join on b.list => 4 instances @@ -80,6 +81,7 @@ public void treatJoinMultipleOneToManyList() { @Test public void treatJoinParentOneToManyList() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -87,8 +89,7 @@ public void treatJoinParentOneToManyList() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements but only two are Sub1 Assert.assertEquals(4, bases.size()); @@ -100,6 +101,7 @@ public void treatJoinParentOneToManyList() { @Test public void treatJoinMultipleParentOneToManyList() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -111,8 +113,7 @@ public void treatJoinMultipleParentOneToManyList() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements, two are Sub1 and the other are Sub2 Assert.assertEquals(4, bases.size()); @@ -124,13 +125,13 @@ public void treatJoinMultipleParentOneToManyList() { @Test public void treatJoinEmbeddableOneToManyList() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b.embeddable.list AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -142,6 +143,8 @@ public void treatJoinEmbeddableOneToManyList() { @Test public void treatJoinMultipleEmbeddableOneToManyList() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b.embeddable.list AS " + strategy + "Sub1)", "s1") @@ -149,8 +152,7 @@ public void treatJoinMultipleEmbeddableOneToManyList() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable.list => 4 instances // Left join on b.embeddable.list => 4 instances @@ -163,6 +165,7 @@ public void treatJoinMultipleEmbeddableOneToManyList() { @Test public void treatJoinParentEmbeddableOneToManyList() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -170,8 +173,7 @@ public void treatJoinParentEmbeddableOneToManyList() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinParentEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements but only two are Sub1 Assert.assertEquals(4, bases.size()); @@ -183,6 +185,7 @@ public void treatJoinParentEmbeddableOneToManyList() { @Test public void treatJoinMultipleParentEmbeddableOneToManyList() { + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -194,8 +197,7 @@ public void treatJoinMultipleParentEmbeddableOneToManyList() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleParentEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements, two are Sub1 and the other are Sub2 Assert.assertEquals(4, bases.size()); @@ -208,25 +210,28 @@ public void treatJoinMultipleParentEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).list1", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).list1", "s1") @@ -234,14 +239,13 @@ public void joinMultipleTreatedRootOneToManyList() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 => 4 instances // Left join on b.list2 => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -249,6 +253,7 @@ public void joinMultipleTreatedRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -256,20 +261,20 @@ public void joinTreatedParentRootOneToManyList() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances - // There are two list elements but only one is Sub1 + // There are two list elements Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -277,17 +282,16 @@ public void joinMultipleTreatedParentRootOneToManyList() { .select("s1.value") .end() .selectSubquery() - .from("TREAT(b AS " + strategy + "Sub1).list2", "s2") + .from("TREAT(b AS " + strategy + "Sub2).list2", "s2") .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -295,25 +299,28 @@ public void joinMultipleTreatedParentRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List", "s1") .select("s1.value") ); - System.out.println("joinTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable.sub1List => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeHibernateSupportsMultiTpcWithTypeExpression(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List", "s1") @@ -321,14 +328,13 @@ public void joinMultipleTreatedRootEmbeddableOneToManyList() { .select("s1.value") .select("s2.value") ); - System.out.println("joinMultipleTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List => 4 instances // Left join on b.embeddable2.sub2List => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -336,6 +342,7 @@ public void joinMultipleTreatedRootEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinTreatedParentRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -343,20 +350,20 @@ public void joinTreatedParentRootEmbeddableOneToManyList() { .select("s1.value") .end() ); - System.out.println("joinTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements but only one is Sub1 Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void joinMultipleTreatedParentRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -368,13 +375,12 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyList() { .select("s2.value") .end() ); - System.out.println("joinMultipleTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -382,13 +388,14 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).list1 AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -401,6 +408,8 @@ public void treatJoinTreatedRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).list1 AS " + strategy + "Sub1)", "s1") @@ -408,8 +417,7 @@ public void treatJoinMultipleTreatedRootOneToManyList() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 => 4 instances // Left join on b.list2 => 4 instances @@ -423,6 +431,8 @@ public void treatJoinMultipleTreatedRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -430,8 +440,7 @@ public void treatJoinTreatedParentRootOneToManyList() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -444,6 +453,8 @@ public void treatJoinTreatedParentRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -455,8 +466,7 @@ public void treatJoinMultipleTreatedParentRootOneToManyList() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); @@ -469,13 +479,14 @@ public void treatJoinMultipleTreatedParentRootOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedRootEmbeddableOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Integer.class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1)", "s1") .select("s1.sub1Value") ); - System.out.println("treatJoinTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List => 4 instances Assert.assertEquals(4, bases.size()); @@ -488,6 +499,8 @@ public void treatJoinTreatedRootEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedRootEmbeddableOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeCollectionTreatJoinWithRootTreatWorks(); List bases = list( from(Object[].class, "Base", "b") .leftJoin("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1)", "s1") @@ -495,8 +508,7 @@ public void treatJoinMultipleTreatedRootEmbeddableOneToManyList() { .select("s1.sub1Value") .select("s2.sub2Value") ); - System.out.println("treatJoinMultipleTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List => 4 instances // Left join on b.embeddable2.sub2List => 4 instances @@ -510,6 +522,8 @@ public void treatJoinMultipleTreatedRootEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinTreatedParentRootEmbeddableOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -517,8 +531,7 @@ public void treatJoinTreatedParentRootEmbeddableOneToManyList() { .select("s1.sub1Value") .end() ); - System.out.println("treatJoinTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements but only one is Sub1 Assert.assertEquals(4, bases.size()); @@ -531,6 +544,8 @@ public void treatJoinTreatedParentRootEmbeddableOneToManyList() { @Test // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete public void treatJoinMultipleTreatedParentRootEmbeddableOneToManyList() { + assumeTreatJoinWithRootTreatSupportedOrEmulated(); + assumeTreatInSubqueryCorrelationWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -542,8 +557,7 @@ public void treatJoinMultipleTreatedParentRootEmbeddableOneToManyList() { .select("s2.sub2Value") .end() ); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/RootTreatTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/RootTreatTest.java index d50e752fe5..0f2cf63c60 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/RootTreatTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/RootTreatTest.java @@ -42,12 +42,12 @@ public static Object[] getParameters() { @Test public void selectTreatedRootBasic() { + assumeTreatInNonPredicateDoesNotFilter(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootBasic-" + strategy); - + // From => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); @@ -58,13 +58,13 @@ public void selectTreatedRootBasic() { @Test public void selectMultipleTreatedRootBasic() { + assumeTreatInNonPredicateDoesNotFilter(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b AS " + strategy + "Sub1).sub1Value") .select("TREAT(b AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootBasic-" + strategy); - + // From => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, new Object[] { 1, null }); @@ -75,6 +75,7 @@ public void selectMultipleTreatedRootBasic() { @Test public void selectTreatedParentRootBasic() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -83,8 +84,7 @@ public void selectTreatedParentRootBasic() { .select("SUM(TREAT(b AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootBasic-" + strategy); - + // From => 4 instances // There are 2 IntIdEntity instances per Base instance // For the 2 Sub1 instances, their sub1Value is doubled @@ -98,6 +98,7 @@ public void selectTreatedParentRootBasic() { @Test public void selectMultipleTreatedParentRootBasic() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -111,8 +112,7 @@ public void selectMultipleTreatedParentRootBasic() { .select("SUM(TREAT(b AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootBasic-" + strategy); - + // From => 4 instances // There are 2 IntIdEntity instances per Base instance // For the 2 Sub1 instances, their sub1Value is doubled @@ -127,12 +127,12 @@ public void selectMultipleTreatedParentRootBasic() { @Test public void selectTreatedRootEmbeddableBasic() { + assumeTreatInNonPredicateDoesNotFilter(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b AS " + strategy + "Sub1).sub1Embeddable.someValue") ); - System.out.println("selectTreatedRootEmbeddableBasic-" + strategy); - + // From => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); @@ -143,13 +143,13 @@ public void selectTreatedRootEmbeddableBasic() { @Test public void selectMultipleTreatedRootEmbeddableBasic() { + assumeTreatInNonPredicateDoesNotFilter(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b AS " + strategy + "Sub1).sub1Embeddable.someValue") .select("TREAT(b AS " + strategy + "Sub2).sub2Embeddable.someValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableBasic-" + strategy); - + // From => 4 instances Assert.assertEquals(4, bases.size()); assertRemoved(bases, new Object[] { null, null }); @@ -160,6 +160,7 @@ public void selectMultipleTreatedRootEmbeddableBasic() { @Test public void selectTreatedParentRootEmbeddableBasic() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -168,8 +169,7 @@ public void selectTreatedParentRootEmbeddableBasic() { .select("SUM(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableBasic-" + strategy); - + // From => 4 instances // There are 2 IntIdEntity instances per Base instance // For the 2 Sub1 instances, their sub1SomeValue is doubled @@ -183,6 +183,7 @@ public void selectTreatedParentRootEmbeddableBasic() { @Test public void selectMultipleTreatedParentRootEmbeddableBasic() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +197,7 @@ public void selectMultipleTreatedParentRootEmbeddableBasic() { .select("SUM(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableBasic-" + strategy); - + // From => 4 instances // There are 2 IntIdEntity instances per Base instance // For the 2 Sub1 instances, their sub1SomeValue is doubled @@ -217,10 +217,26 @@ public void whereTreatedRootBasic() { .select("b.name") .where("COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0)").ltExpression("100") ); - System.out.println("whereTreatedRootBasic-" + strategy); + + // From => 4 instances + // Where => 1 instance because 1 Sub1 has sub1Value 101, the others are Sub2s + Assert.assertEquals(1, bases.size()); + assertRemoved(bases, objectPrefix + "1"); + } + + @Test + public void whereTreatedRootBasicOr() { + List bases = list( + from(String.class, "Base", "b") + .select("b.name") + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub1") + .where("COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0)").ltExpression("100") + .endOr() + ); // From => 4 instances - // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce + // Where => 3 instance because 1 Sub1 has sub1Value 101, the others are Sub2s Assert.assertEquals(3, bases.size()); assertRemoved(bases, objectPrefix + "2.parent"); assertRemoved(bases, objectPrefix + "1"); @@ -235,16 +251,35 @@ public void whereMultipleTreatedRootBasic() { .where("COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0)").ltExpression("100") .where("COALESCE(TREAT(b AS " + strategy + "Sub2).sub2Value, 0)").ltExpression("100") ); - System.out.println("whereMultipleTreatedRootBasic-" + strategy); + + // From => 4 instances + // Where => 0 instances because one variable can't be treated with 2 different subtypes in a single AND predicate + Assert.assertEquals(0, bases.size()); + } + + @Test + public void whereMultipleTreatedRootBasicOr() { + List bases = list( + from(String.class, "Base", "b") + .select("b.name") + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub1") + .where("COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0)").ltExpression("100") + .endOr() + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub2") + .where("COALESCE(TREAT(b AS " + strategy + "Sub2).sub2Value, 0)").ltExpression("100") + .endOr() + ); // From => 4 instances - // Where => 2 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce - // and 1 Sub2 has sub2Value 102, the other has 2 and Sub1 uses 0 because of coalesce + // Where => 2 instances because 1 Sub1 has sub1Value 101, the other has 1 + // 1 Sub2 has sub2Value 102, the other has 2 Assert.assertEquals(2, bases.size()); assertRemoved(bases, objectPrefix + "1"); assertRemoved(bases, objectPrefix + "2"); } - + @Test public void whereTreatedRootEmbeddableBasic() { List bases = list( @@ -252,8 +287,24 @@ public void whereTreatedRootEmbeddableBasic() { .select("b.name") .where("COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0)").ltExpression("100") ); - System.out.println("whereTreatedRootEmbeddableBasic-" + strategy); + // From => 4 instances + // Where => 1 instance because 1 Sub1 has sub1Value 101, the others are Sub2s + Assert.assertEquals(1, bases.size()); + assertRemoved(bases, objectPrefix + "1"); + } + + @Test + public void whereTreatedRootEmbeddableBasicOr() { + List bases = list( + from(String.class, "Base", "b") + .select("b.name") + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub1") + .where("COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0)").ltExpression("100") + .endOr() + ); + // From => 4 instances // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce Assert.assertEquals(3, bases.size()); @@ -270,11 +321,30 @@ public void whereMultipleTreatedRootEmbeddableBasic() { .where("COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0)").ltExpression("100") .where("COALESCE(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2SomeValue, 0)").ltExpression("100") ); - System.out.println("whereMultipleTreatedRootEmbeddableBasic-" + strategy); + + // From => 4 instances + // Where => 0 instances because one variable can't be treated with 2 different subtypes in a single AND predicate + Assert.assertEquals(0, bases.size()); + } + + @Test + public void whereMultipleTreatedRootEmbeddableBasicOr() { + List bases = list( + from(String.class, "Base", "b") + .select("b.name") + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub1") + .where("COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0)").ltExpression("100") + .endOr() + .whereOr() + .where("TYPE(b)").notEqExpression(strategy + "Sub2") + .where("COALESCE(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2SomeValue, 0)").ltExpression("100") + .endOr() + ); // From => 4 instances - // Where => 2 instances because 1 Sub1 has sub1SomeValue 101, the other has 1 and Sub2s use 0 because of coalesce - // and 1 Sub2 has sub2SomeValue 102, the other has 2 and Sub1 uses 0 because of coalesce + // Where => 2 instances because 1 Sub1 has sub1SomeValue 101, the other has 1 + // 1 Sub2 has sub2SomeValue 102, the other has 2 Assert.assertEquals(2, bases.size()); assertRemoved(bases, objectPrefix + "1"); assertRemoved(bases, objectPrefix + "2"); @@ -287,8 +357,7 @@ public void whereTreatedRootConditionBasic() { .select("b.name") .where("TREAT(b AS " + strategy + "Sub1).sub1Value").eqExpression("101") ); - System.out.println("whereTreatedRootConditionBasic-" + strategy); - + // From => 4 instances // Where => 1 instance because 1 Sub1 has sub1Value 101 Assert.assertEquals(1, bases.size()); @@ -306,8 +375,7 @@ public void whereMultipleTreatedRootConditionBasic() { .endOr() ); - System.out.println("whereMultipleTreatedRootConditionBasic-" + strategy); - + // From => 4 instances // Where => 2 instances because 1 Sub1 has sub1Value 101 and 1 Sub2 has sub2Value 102 Assert.assertEquals(2, bases.size()); @@ -322,8 +390,7 @@ public void whereTreatedRootConditionEmbeddableBasic() { .select("b.name") .where("TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue").eqExpression("101") ); - System.out.println("whereTreatedRootConditionEmbeddableBasic-" + strategy); - + // From => 4 instances // Where => 1 instance because 1 Sub1 has sub1SomeValue 101 Assert.assertEquals(1, bases.size()); @@ -341,8 +408,7 @@ public void whereMultipleTreatedRootConditionEmbeddableBasic() { .endOr() ); - System.out.println("whereMultipleTreatedRootConditionEmbeddableBasic-" + strategy); - + // From => 4 instances // Where => 2 instances because 1 Sub1 has sub1SomeValue 101 and 1 Sub2 has sub2SomeValue 102 Assert.assertEquals(2, bases.size()); @@ -357,12 +423,6 @@ public void whereTreatedRootConditionNegated() { .select("b.name") .whereExpression("NOT(TREAT(b AS " + strategy + "Sub1).sub1Value = 101)") ); - System.out.println("whereTreatedRootConditionNegated-" + strategy); - - // NOTE: Fixing this one here is extra tricky but more or less follows the scheme - // A predicate involving a treat like "TREAT(b AS " + strategy + "Sub1).sub1Value = 101" - // Is like doing "TYPE(b) = Sub1 AND TREAT(b AS Sub1).sub1Value = 101" - // Having the "NOT" around that should make this "TYPE(b) <> Sub1 OR TREAT(b AS Sub1).sub1Value <> 101" // From => 4 instances // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s are included because type constraint is inverted @@ -379,8 +439,7 @@ public void whereMultipleTreatedRootConditionNegated() { .select("b.name") .whereExpression("NOT(TREAT(b AS " + strategy + "Sub1).sub1Value = 101) AND NOT(TREAT(b AS " + strategy + "Sub2).sub2Value = 102)") ); - System.out.println("whereMultipleTreatedRootConditionNegated-" + strategy); - + // From => 4 instances // Where => 2 instances because 1 Sub1 has sub1Value 101 and 1 Sub2 has sub2Value 102 Assert.assertEquals(2, bases.size()); @@ -395,8 +454,7 @@ public void whereTreatedRootConditionSuperTypeAccess() { .select("b.name") .where("TREAT(b AS " + strategy + "Sub1).value").gtExpression("100") ); - System.out.println("whereTreatedRootConditionSuperTypeAccess-" + strategy); - + // From => 4 instances // Where => 1 instance because 1 Sub1 has value 101, the other has 1 and Sub2s are excluded because of type constraint Assert.assertEquals(1, bases.size()); @@ -413,8 +471,7 @@ public void whereMultipleTreatedRootConditionSuperTypeAccess() { .where("TREAT(b AS " + strategy + "Sub2).value").ltExpression("100") .endOr() ); - System.out.println("whereMultipleTreatedRootConditionSuperTypeAccess-" + strategy); - + // From => 4 instances // Where => 2 instances because 1 Sub1 has value 101 and 1 Sub2 has value 102 the has value 1 Assert.assertEquals(2, bases.size()); diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapKeyTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapKeyTest.java index 7c19e172c3..9960a1c711 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapKeyTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapKeyTest.java @@ -24,6 +24,9 @@ import java.util.List; +/** + * This test de-references map keys for which the support came in Hibernate 5.2. + */ @RunWith(Parameterized.class) public class SelectManyToManyMapKeyTest extends AbstractTreatVariationsTest { @@ -42,12 +45,13 @@ public static Object[] getParameters() { @Test public void selectTreatedManyToManyMapKey() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeTreatMapAssociationIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(b.map) AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,13 +63,14 @@ public void selectTreatedManyToManyMapKey() { @Test public void selectMultipleTreatedManyToManyMapKey() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeTreatMapAssociationIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(b.map) AS " + strategy + "Sub1).sub1Value") .select("TREAT(KEY(b.map) AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -77,6 +82,8 @@ public void selectMultipleTreatedManyToManyMapKey() { @Test public void selectTreatedParentManyToManyMapKey() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -85,8 +92,7 @@ public void selectTreatedParentManyToManyMapKey() { .select("SUM(TREAT(KEY(b.map) AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys but only two are Sub1 // The sub1Value is doubled @@ -99,6 +105,8 @@ public void selectTreatedParentManyToManyMapKey() { @Test public void selectMultipleTreatedParentManyToManyMapKey() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -112,8 +120,7 @@ public void selectMultipleTreatedParentManyToManyMapKey() { .select("SUM(TREAT(KEY(b.map) AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -126,12 +133,13 @@ public void selectMultipleTreatedParentManyToManyMapKey() { @Test public void selectTreatedEmbeddableManyToManyMapKey() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -143,13 +151,14 @@ public void selectTreatedEmbeddableManyToManyMapKey() { @Test public void selectMultipleTreatedEmbeddableManyToManyMapKey() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).sub1Value") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -161,6 +170,8 @@ public void selectMultipleTreatedEmbeddableManyToManyMapKey() { @Test public void selectTreatedParentEmbeddableManyToManyMapKey() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -169,8 +180,7 @@ public void selectTreatedParentEmbeddableManyToManyMapKey() { .select("SUM(TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys but only two are Sub1 // The sub1Value is doubled @@ -183,6 +193,8 @@ public void selectTreatedParentEmbeddableManyToManyMapKey() { @Test public void selectMultipleTreatedParentEmbeddableManyToManyMapKey() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +208,7 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapKey() { .select("SUM(TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -210,12 +221,13 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapKey() { @Test public void selectTreatedEmbeddableManyToManyMapKeyEmbeddable() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,13 +239,14 @@ public void selectTreatedEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectMultipleTreatedEmbeddableManyToManyMapKeyEmbeddable() { + assumeQueryLanguageSupportsKeyDeReference(); + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable.map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -245,6 +258,8 @@ public void selectMultipleTreatedEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -253,8 +268,7 @@ public void selectTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { .select("SUM(TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // There are four map keys but only two are Sub1 // The sub1Value is doubled @@ -267,6 +281,8 @@ public void selectTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectMultipleTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -280,8 +296,7 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { .select("SUM(TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // There are four map keys, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -294,12 +309,13 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectTreatedRootManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.map1) => 4 instances Assert.assertEquals(4, bases.size()); @@ -311,13 +327,14 @@ public void selectTreatedRootManyToManyMapKey() { @Test public void selectMultipleTreatedRootManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1).sub1Value") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.map1) and KEY(b.map2) => 4 instances // There are four map keys, one is Sub1 and the other Sub2 @@ -330,6 +347,8 @@ public void selectMultipleTreatedRootManyToManyMapKey() { @Test public void selectTreatedParentRootManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -338,8 +357,7 @@ public void selectTreatedParentRootManyToManyMapKey() { .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys but only one is Sub1 // The sub1Value is doubled @@ -352,6 +370,8 @@ public void selectTreatedParentRootManyToManyMapKey() { @Test public void selectMultipleTreatedParentRootManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -365,8 +385,7 @@ public void selectMultipleTreatedParentRootManyToManyMapKey() { .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -379,12 +398,13 @@ public void selectMultipleTreatedParentRootManyToManyMapKey() { @Test public void selectTreatedRootEmbeddableManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable1.sub1Map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -396,13 +416,14 @@ public void selectTreatedRootEmbeddableManyToManyMapKey() { @Test public void selectMultipleTreatedRootEmbeddableManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).sub1Value") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable1.sub1Map) and KEY(b.embeddable2.sub2Map) => 4 instances // There are four map keys, one is Sub1 and the other Sub2 @@ -415,6 +436,8 @@ public void selectMultipleTreatedRootEmbeddableManyToManyMapKey() { @Test public void selectTreatedParentRootEmbeddableManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -423,8 +446,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapKey() { .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys but only one is Sub1 // The sub1Value is doubled @@ -437,6 +459,8 @@ public void selectTreatedParentRootEmbeddableManyToManyMapKey() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToManyMapKey() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -450,8 +474,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapKey() { .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - + // From => 4 instances // There are four map keys, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -464,12 +487,13 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapKey() { @Test public void selectTreatedRootEmbeddableManyToManyMapKeyEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedRootEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable1.sub1Map) => 4 instances Assert.assertEquals(4, bases.size()); @@ -481,13 +505,14 @@ public void selectTreatedRootEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectMultipleTreatedRootEmbeddableManyToManyMapKeyEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // Left join on KEY(b.embeddable1.sub1Map) and KEY(b.embeddable2.sub2Map) => 4 instances // There are four map keys, one is Sub1 and the other Sub2 @@ -500,6 +525,8 @@ public void selectMultipleTreatedRootEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -508,8 +535,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable() { .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // There are four map keys but only one is Sub1 // The sub1Value is doubled @@ -522,6 +548,8 @@ public void selectTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); + assumeQueryLanguageSupportsKeyDeReference(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -535,8 +563,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable( .select("SUM(TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToManyMapKeyEmbeddable-" + strategy); - + // From => 4 instances // There are four map keys, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapValueTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapValueTest.java index 8b522aec9c..f159618176 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapValueTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToManyMapValueTest.java @@ -42,12 +42,12 @@ public static Object[] getParameters() { @Test public void selectTreatedManyToManyMapValue() { + assumeTreatMapAssociationIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.map AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,13 +59,13 @@ public void selectTreatedManyToManyMapValue() { @Test public void selectMultipleTreatedManyToManyMapValue() { + assumeTreatMapAssociationIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.map AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.map AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -77,6 +77,7 @@ public void selectMultipleTreatedManyToManyMapValue() { @Test public void selectTreatedParentManyToManyMapValue() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -85,8 +86,7 @@ public void selectTreatedParentManyToManyMapValue() { .select("SUM(TREAT(b.map AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values but only two are Sub1 // The sub1Value is doubled @@ -99,6 +99,7 @@ public void selectTreatedParentManyToManyMapValue() { @Test public void selectMultipleTreatedParentManyToManyMapValue() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -112,8 +113,7 @@ public void selectMultipleTreatedParentManyToManyMapValue() { .select("SUM(TREAT(b.map AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -126,12 +126,12 @@ public void selectMultipleTreatedParentManyToManyMapValue() { @Test public void selectTreatedEmbeddableManyToManyMapValue() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.map AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -143,13 +143,13 @@ public void selectTreatedEmbeddableManyToManyMapValue() { @Test public void selectMultipleTreatedEmbeddableManyToManyMapValue() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.map AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.embeddable.map AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -161,6 +161,7 @@ public void selectMultipleTreatedEmbeddableManyToManyMapValue() { @Test public void selectTreatedParentEmbeddableManyToManyMapValue() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -169,8 +170,7 @@ public void selectTreatedParentEmbeddableManyToManyMapValue() { .select("SUM(TREAT(b.embeddable.map AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values but only two are Sub1 // The sub1Value is doubled @@ -183,6 +183,7 @@ public void selectTreatedParentEmbeddableManyToManyMapValue() { @Test public void selectMultipleTreatedParentEmbeddableManyToManyMapValue() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +197,7 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapValue() { .select("SUM(TREAT(b.embeddable.map AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are four map values, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -210,12 +210,12 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapValue() { @Test public void selectTreatedEmbeddableManyToManyMapValueEmbeddable() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.map AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,13 +227,13 @@ public void selectTreatedEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectMultipleTreatedEmbeddableManyToManyMapValueEmbeddable() { + assumeMapInEmbeddableIsSupported(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.map AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(b.embeddable.map AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable.map => 4 instances Assert.assertEquals(4, bases.size()); @@ -245,6 +245,7 @@ public void selectMultipleTreatedEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectTreatedParentEmbeddableManyToManyMapValueEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -253,8 +254,7 @@ public void selectTreatedParentEmbeddableManyToManyMapValueEmbeddable() { .select("SUM(TREAT(b.embeddable.map AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // There are four map values but only two are Sub1 // The sub1Value is doubled @@ -267,6 +267,7 @@ public void selectTreatedParentEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectMultipleTreatedParentEmbeddableManyToManyMapValueEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -280,8 +281,7 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapValueEmbeddable() .select("SUM(TREAT(b.embeddable.map AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // There are four map values, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -294,12 +294,12 @@ public void selectMultipleTreatedParentEmbeddableManyToManyMapValueEmbeddable() @Test public void selectTreatedRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).map1 AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -311,13 +311,13 @@ public void selectTreatedRootManyToManyMapValue() { @Test public void selectMultipleTreatedRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).map1 AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).map2 AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.map1 and b.map2 => 4 instances Assert.assertEquals(4, bases.size()); @@ -329,6 +329,7 @@ public void selectMultipleTreatedRootManyToManyMapValue() { @Test public void selectTreatedParentRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -337,8 +338,7 @@ public void selectTreatedParentRootManyToManyMapValue() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).map1 AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values but only one is Sub1 // The sub1Value is doubled @@ -351,6 +351,7 @@ public void selectTreatedParentRootManyToManyMapValue() { @Test public void selectMultipleTreatedParentRootManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -364,8 +365,7 @@ public void selectMultipleTreatedParentRootManyToManyMapValue() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).map2 AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -378,12 +378,12 @@ public void selectMultipleTreatedParentRootManyToManyMapValue() { @Test public void selectTreatedRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Map => 4 instances Assert.assertEquals(4, bases.size()); @@ -395,13 +395,13 @@ public void selectTreatedRootEmbeddableManyToManyMapValue() { @Test public void selectMultipleTreatedRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Map and b.embeddable2.sub2Map => 4 instances Assert.assertEquals(4, bases.size()); @@ -413,6 +413,7 @@ public void selectMultipleTreatedRootEmbeddableManyToManyMapValue() { @Test public void selectTreatedParentRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -421,8 +422,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapValue() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values but only one is Sub1 // The sub1Value is doubled @@ -435,6 +435,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapValue() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToManyMapValue() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -448,8 +449,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapValue() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -462,12 +462,12 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapValue() { @Test public void selectTreatedRootEmbeddableManyToManyMapValueEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedRootEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Map => 4 instances Assert.assertEquals(4, bases.size()); @@ -479,13 +479,13 @@ public void selectTreatedRootEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectMultipleTreatedRootEmbeddableManyToManyMapValueEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Map and b.embeddable2.sub2Map => 4 instances Assert.assertEquals(4, bases.size()); @@ -497,6 +497,7 @@ public void selectMultipleTreatedRootEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectTreatedParentRootEmbeddableManyToManyMapValueEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -505,8 +506,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapValueEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // There are two map values but only one is Sub1 // The sub1Value is doubled @@ -519,6 +519,7 @@ public void selectTreatedParentRootEmbeddableManyToManyMapValueEmbeddable() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToManyMapValueEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -532,8 +533,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToManyMapValueEmbeddabl .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToManyMapValueEmbeddable-" + strategy); - + // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToOneTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToOneTest.java index 826768a1c7..7c7500dff3 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToOneTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectManyToOneTest.java @@ -42,12 +42,12 @@ public static Object[] getParameters() { @Test public void selectTreatedManyToOne() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.parent AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,13 +59,14 @@ public void selectTreatedManyToOne() { @Test public void selectMultipleTreatedManyToOne() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.parent AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.parent AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -77,6 +78,7 @@ public void selectMultipleTreatedManyToOne() { @Test public void selectTreatedParentManyToOne() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -85,8 +87,7 @@ public void selectTreatedParentManyToOne() { .select("SUM(TREAT(b.parent AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -99,6 +100,7 @@ public void selectTreatedParentManyToOne() { @Test public void selectMultipleTreatedParentManyToOne() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -112,8 +114,7 @@ public void selectMultipleTreatedParentManyToOne() { .select("SUM(TREAT(b.parent AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -126,12 +127,12 @@ public void selectMultipleTreatedParentManyToOne() { @Test public void selectTreatedEmbeddableManyToOne() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -143,13 +144,14 @@ public void selectTreatedEmbeddableManyToOne() { @Test public void selectMultipleTreatedEmbeddableManyToOne() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -161,6 +163,7 @@ public void selectMultipleTreatedEmbeddableManyToOne() { @Test public void selectTreatedParentEmbeddableManyToOne() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -169,8 +172,7 @@ public void selectTreatedParentEmbeddableManyToOne() { .select("SUM(TREAT(b.embeddable.parent AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -183,6 +185,7 @@ public void selectTreatedParentEmbeddableManyToOne() { @Test public void selectMultipleTreatedParentEmbeddableManyToOne() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +199,7 @@ public void selectMultipleTreatedParentEmbeddableManyToOne() { .select("SUM(TREAT(b.embeddable.parent AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -210,12 +212,12 @@ public void selectMultipleTreatedParentEmbeddableManyToOne() { @Test public void selectTreatedEmbeddableManyToOneEmbeddable() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,13 +229,14 @@ public void selectTreatedEmbeddableManyToOneEmbeddable() { @Test public void selectMultipleTreatedEmbeddableManyToOneEmbeddable() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(b.embeddable.parent AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -245,6 +248,7 @@ public void selectMultipleTreatedEmbeddableManyToOneEmbeddable() { @Test public void selectTreatedParentEmbeddableManyToOneEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -253,8 +257,7 @@ public void selectTreatedParentEmbeddableManyToOneEmbeddable() { .select("SUM(TREAT(b.embeddable.parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -267,6 +270,7 @@ public void selectTreatedParentEmbeddableManyToOneEmbeddable() { @Test public void selectMultipleTreatedParentEmbeddableManyToOneEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -280,8 +284,7 @@ public void selectMultipleTreatedParentEmbeddableManyToOneEmbeddable() { .select("SUM(TREAT(b.embeddable.parent AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -294,12 +297,12 @@ public void selectMultipleTreatedParentEmbeddableManyToOneEmbeddable() { @Test public void selectTreatedRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).parent1 AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -311,13 +314,13 @@ public void selectTreatedRootManyToOne() { @Test public void selectMultipleTreatedRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).parent1 AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).parent2 AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootManyToOne-" + strategy); - + // From => 4 instances // Left join on b.parent1 and b.parent2 => 4 instances Assert.assertEquals(4, bases.size()); @@ -329,6 +332,7 @@ public void selectMultipleTreatedRootManyToOne() { @Test public void selectTreatedParentRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -337,8 +341,7 @@ public void selectTreatedParentRootManyToOne() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).parent1 AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -351,6 +354,7 @@ public void selectTreatedParentRootManyToOne() { @Test public void selectMultipleTreatedParentRootManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -364,8 +368,7 @@ public void selectMultipleTreatedParentRootManyToOne() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).parent2 AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -378,12 +381,12 @@ public void selectMultipleTreatedParentRootManyToOne() { @Test public void selectTreatedRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -395,13 +398,13 @@ public void selectTreatedRootEmbeddableManyToOne() { @Test public void selectMultipleTreatedRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent and b.embeddable2.sub2Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -413,6 +416,7 @@ public void selectMultipleTreatedRootEmbeddableManyToOne() { @Test public void selectTreatedParentRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -421,8 +425,7 @@ public void selectTreatedParentRootEmbeddableManyToOne() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -435,6 +438,7 @@ public void selectTreatedParentRootEmbeddableManyToOne() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToOne() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -448,8 +452,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToOne() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToOne-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -462,12 +465,12 @@ public void selectMultipleTreatedParentRootEmbeddableManyToOne() { @Test public void selectTreatedRootEmbeddableManyToOneEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedRootEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -479,13 +482,13 @@ public void selectTreatedRootEmbeddableManyToOneEmbeddable() { @Test public void selectMultipleTreatedRootEmbeddableManyToOneEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Parent and b.embeddable2.sub1Parent => 4 instances Assert.assertEquals(4, bases.size()); @@ -497,6 +500,7 @@ public void selectMultipleTreatedRootEmbeddableManyToOneEmbeddable() { @Test public void selectTreatedParentRootEmbeddableManyToOneEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -505,8 +509,7 @@ public void selectTreatedParentRootEmbeddableManyToOneEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // There are two parents but only one is Sub1 // The sub1Value is doubled @@ -519,6 +522,7 @@ public void selectTreatedParentRootEmbeddableManyToOneEmbeddable() { @Test public void selectMultipleTreatedParentRootEmbeddableManyToOneEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -532,8 +536,7 @@ public void selectMultipleTreatedParentRootEmbeddableManyToOneEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableManyToOneEmbeddable-" + strategy); - + // From => 4 instances // There are two parents, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyInverseSetTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyInverseSetTest.java index 75f4917561..14fccb1f27 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyInverseSetTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyInverseSetTest.java @@ -42,12 +42,12 @@ public static Object[] getParameters() { @Test public void selectTreatedOneToManyInverseSet() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.children AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,13 +59,14 @@ public void selectTreatedOneToManyInverseSet() { @Test public void selectMultipleTreatedOneToManyInverseSet() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.children AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.children AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -77,6 +78,7 @@ public void selectMultipleTreatedOneToManyInverseSet() { @Test public void selectTreatedParentOneToManyInverseSet() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -85,8 +87,7 @@ public void selectTreatedParentOneToManyInverseSet() { .select("SUM(TREAT(b.children AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -99,6 +100,7 @@ public void selectTreatedParentOneToManyInverseSet() { @Test public void selectMultipleTreatedParentOneToManyInverseSet() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -112,8 +114,7 @@ public void selectMultipleTreatedParentOneToManyInverseSet() { .select("SUM(TREAT(b.children AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -126,12 +127,12 @@ public void selectMultipleTreatedParentOneToManyInverseSet() { @Test public void selectTreatedEmbeddableOneToManyInverseSet() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.children AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -143,13 +144,14 @@ public void selectTreatedEmbeddableOneToManyInverseSet() { @Test public void selectMultipleTreatedEmbeddableOneToManyInverseSet() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.children AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.embeddable.children AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -161,6 +163,7 @@ public void selectMultipleTreatedEmbeddableOneToManyInverseSet() { @Test public void selectTreatedParentEmbeddableOneToManyInverseSet() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -169,8 +172,7 @@ public void selectTreatedParentEmbeddableOneToManyInverseSet() { .select("SUM(TREAT(b.embeddable.children AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -183,6 +185,7 @@ public void selectTreatedParentEmbeddableOneToManyInverseSet() { @Test public void selectMultipleTreatedParentEmbeddableOneToManyInverseSet() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +199,7 @@ public void selectMultipleTreatedParentEmbeddableOneToManyInverseSet() { .select("SUM(TREAT(b.embeddable.children AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -210,12 +212,12 @@ public void selectMultipleTreatedParentEmbeddableOneToManyInverseSet() { @Test public void selectTreatedEmbeddableOneToManyInverseSetEmbeddable() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.children AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,13 +229,14 @@ public void selectTreatedEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectMultipleTreatedEmbeddableOneToManyInverseSetEmbeddable() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.children AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(b.embeddable.children AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.children => 4 instances Assert.assertEquals(4, bases.size()); @@ -245,6 +248,7 @@ public void selectMultipleTreatedEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectTreatedParentEmbeddableOneToManyInverseSetEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -253,8 +257,7 @@ public void selectTreatedParentEmbeddableOneToManyInverseSetEmbeddable() { .select("SUM(TREAT(b.embeddable.children AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -267,6 +270,7 @@ public void selectTreatedParentEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectMultipleTreatedParentEmbeddableOneToManyInverseSetEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -280,8 +284,7 @@ public void selectMultipleTreatedParentEmbeddableOneToManyInverseSetEmbeddable() .select("SUM(TREAT(b.embeddable.children AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -294,12 +297,12 @@ public void selectMultipleTreatedParentEmbeddableOneToManyInverseSetEmbeddable() @Test public void selectTreatedRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).children1 AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -311,13 +314,13 @@ public void selectTreatedRootOneToManyInverseSet() { @Test public void selectMultipleTreatedRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).children1 AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).children2 AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.children1 and b.children2 => 4 instances Assert.assertEquals(4, bases.size()); @@ -329,6 +332,7 @@ public void selectMultipleTreatedRootOneToManyInverseSet() { @Test public void selectTreatedParentRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -337,8 +341,7 @@ public void selectTreatedParentRootOneToManyInverseSet() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).children1 AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -351,6 +354,7 @@ public void selectTreatedParentRootOneToManyInverseSet() { @Test public void selectMultipleTreatedParentRootOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -364,8 +368,7 @@ public void selectMultipleTreatedParentRootOneToManyInverseSet() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).children2 AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -378,15 +381,15 @@ public void selectMultipleTreatedParentRootOneToManyInverseSet() { @Test public void selectTreatedRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") - .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub2Children AS " + strategy + "Sub1).sub1Value") + .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances - Assert.assertEquals(1, bases.size()); + Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); assertRemoved(bases, null); @@ -395,13 +398,13 @@ public void selectTreatedRootEmbeddableOneToManyInverseSet() { @Test public void selectMultipleTreatedRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children and b.embeddable2.sub2Children => 4 instances assertRemoved(bases, new Object[] { null, null }); @@ -412,6 +415,7 @@ public void selectMultipleTreatedRootEmbeddableOneToManyInverseSet() { @Test public void selectTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -420,8 +424,7 @@ public void selectTreatedParentRootEmbeddableOneToManyInverseSet() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -434,6 +437,7 @@ public void selectTreatedParentRootEmbeddableOneToManyInverseSet() { @Test public void selectMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -447,8 +451,7 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -461,12 +464,12 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { @Test public void selectTreatedRootEmbeddableOneToManyInverseSetEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedRootEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children => 4 instances Assert.assertEquals(4, bases.size()); @@ -478,13 +481,13 @@ public void selectTreatedRootEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectMultipleTreatedRootEmbeddableOneToManyInverseSetEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1Children and b.embeddable2.sub2Children => 4 instances Assert.assertEquals(4, bases.size()); @@ -496,6 +499,7 @@ public void selectMultipleTreatedRootEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -504,8 +508,7 @@ public void selectTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // There are two children but only one is Sub1 // The sub1Value is doubled @@ -518,6 +521,7 @@ public void selectTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable() { @Test public void selectMultipleTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -531,8 +535,7 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyInverseSetEmbeddab .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableOneToManyInverseSetEmbeddable-" + strategy); - + // From => 4 instances // There are two children, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyListTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyListTest.java index 0d571044e3..c34d0fd9b8 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyListTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/builder/SelectOneToManyListTest.java @@ -42,12 +42,12 @@ public static Object[] getParameters() { @Test public void selectTreatedOneToManyList() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.list AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -59,13 +59,14 @@ public void selectTreatedOneToManyList() { @Test public void selectMultipleTreatedOneToManyList() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.list AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.list AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -77,6 +78,7 @@ public void selectMultipleTreatedOneToManyList() { @Test public void selectTreatedParentOneToManyList() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -85,8 +87,7 @@ public void selectTreatedParentOneToManyList() { .select("SUM(TREAT(b.list AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements but only two are Sub1 // The sub1Value is doubled @@ -99,6 +100,7 @@ public void selectTreatedParentOneToManyList() { @Test public void selectMultipleTreatedParentOneToManyList() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -112,8 +114,7 @@ public void selectMultipleTreatedParentOneToManyList() { .select("SUM(TREAT(b.list AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -126,12 +127,12 @@ public void selectMultipleTreatedParentOneToManyList() { @Test public void selectTreatedEmbeddableOneToManyList() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.list AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -143,13 +144,14 @@ public void selectTreatedEmbeddableOneToManyList() { @Test public void selectMultipleTreatedEmbeddableOneToManyList() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.list AS " + strategy + "Sub1).sub1Value") .select("TREAT(b.embeddable.list AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -161,6 +163,7 @@ public void selectMultipleTreatedEmbeddableOneToManyList() { @Test public void selectTreatedParentEmbeddableOneToManyList() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -169,8 +172,7 @@ public void selectTreatedParentEmbeddableOneToManyList() { .select("SUM(TREAT(b.embeddable.list AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements but only two are Sub1 // The sub1Value is doubled @@ -183,6 +185,7 @@ public void selectTreatedParentEmbeddableOneToManyList() { @Test public void selectMultipleTreatedParentEmbeddableOneToManyList() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -196,8 +199,7 @@ public void selectMultipleTreatedParentEmbeddableOneToManyList() { .select("SUM(TREAT(b.embeddable.list AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are four list elements, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -210,12 +212,12 @@ public void selectMultipleTreatedParentEmbeddableOneToManyList() { @Test public void selectTreatedEmbeddableOneToManyListEmbeddable() { + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(b.embeddable.list AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -227,13 +229,14 @@ public void selectTreatedEmbeddableOneToManyListEmbeddable() { @Test public void selectMultipleTreatedEmbeddableOneToManyListEmbeddable() { + assumeMultipleTreatJoinWithSingleTableIsNotBroken(); + assumeLeftTreatJoinWithSingleTableIsNotBroken(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(b.embeddable.list AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(b.embeddable.list AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.list => 4 instances Assert.assertEquals(4, bases.size()); @@ -245,6 +248,7 @@ public void selectMultipleTreatedEmbeddableOneToManyListEmbeddable() { @Test public void selectTreatedParentEmbeddableOneToManyListEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -253,8 +257,7 @@ public void selectTreatedParentEmbeddableOneToManyListEmbeddable() { .select("SUM(TREAT(b.embeddable.list AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // There are four list elements but only two are Sub1 // The sub1Value is doubled @@ -267,6 +270,7 @@ public void selectTreatedParentEmbeddableOneToManyListEmbeddable() { @Test public void selectMultipleTreatedParentEmbeddableOneToManyListEmbeddable() { + assumeAccessTreatedOuterQueryVariableWorks(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -280,8 +284,7 @@ public void selectMultipleTreatedParentEmbeddableOneToManyListEmbeddable() { .select("SUM(TREAT(b.embeddable.list AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // There are four list elements, two are Sub1 and the other are Sub2 // The sub1Value and sub2Value is doubled @@ -294,12 +297,12 @@ public void selectMultipleTreatedParentEmbeddableOneToManyListEmbeddable() { @Test public void selectTreatedRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).list1 AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 => 4 instances Assert.assertEquals(4, bases.size()); @@ -311,13 +314,13 @@ public void selectTreatedRootOneToManyList() { @Test public void selectMultipleTreatedRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).list1 AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).list2 AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.list1 and b.list2 => 4 instances Assert.assertEquals(4, bases.size()); @@ -329,6 +332,7 @@ public void selectMultipleTreatedRootOneToManyList() { @Test public void selectTreatedParentRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -337,8 +341,7 @@ public void selectTreatedParentRootOneToManyList() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).list1 AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements but only one is Sub1 // The sub1Value is doubled @@ -351,6 +354,7 @@ public void selectTreatedParentRootOneToManyList() { @Test public void selectMultipleTreatedParentRootOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -364,8 +368,7 @@ public void selectMultipleTreatedParentRootOneToManyList() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).list2 AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -378,12 +381,12 @@ public void selectMultipleTreatedParentRootOneToManyList() { @Test public void selectTreatedRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).sub1Value") ); - System.out.println("selectTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List => 4 instances Assert.assertEquals(4, bases.size()); @@ -395,13 +398,13 @@ public void selectTreatedRootEmbeddableOneToManyList() { @Test public void selectMultipleTreatedRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).sub1Value") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List AS " + strategy + "Sub2).sub2Value") ); - System.out.println("selectMultipleTreatedRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List and b.embeddable2.sub2List => 4 instances Assert.assertEquals(4, bases.size()); @@ -413,6 +416,7 @@ public void selectMultipleTreatedRootEmbeddableOneToManyList() { @Test public void selectTreatedParentRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -421,8 +425,7 @@ public void selectTreatedParentRootEmbeddableOneToManyList() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).sub1Value)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements but only is Sub1 // The sub1Value is doubled @@ -435,6 +438,7 @@ public void selectTreatedParentRootEmbeddableOneToManyList() { @Test public void selectMultipleTreatedParentRootEmbeddableOneToManyList() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -448,8 +452,7 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyList() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List AS " + strategy + "Sub2).sub2Value)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableOneToManyList-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled @@ -462,12 +465,12 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyList() { @Test public void selectTreatedRootEmbeddableOneToManyListEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).embeddable1.sub1SomeValue") ); - System.out.println("selectTreatedRootEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List => 4 instances Assert.assertEquals(4, bases.size()); @@ -479,13 +482,13 @@ public void selectTreatedRootEmbeddableOneToManyListEmbeddable() { @Test public void selectMultipleTreatedRootEmbeddableOneToManyListEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .select("TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).embeddable1.sub1SomeValue") .select("TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List AS " + strategy + "Sub2).embeddable2.sub2SomeValue") ); - System.out.println("selectMultipleTreatedRootEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // Left join on b.embeddable1.sub1List and b.embeddable2.sub2List => 4 instances Assert.assertEquals(4, bases.size()); @@ -497,6 +500,7 @@ public void selectMultipleTreatedRootEmbeddableOneToManyListEmbeddable() { @Test public void selectTreatedParentRootEmbeddableOneToManyListEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Integer.class, "Base", "b") .selectSubquery() @@ -505,8 +509,7 @@ public void selectTreatedParentRootEmbeddableOneToManyListEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List AS " + strategy + "Sub1).embeddable1.sub1SomeValue)") .end() ); - System.out.println("selectTreatedParentRootEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // There are two list elements but only one is Sub1 // The sub1Value is doubled @@ -519,6 +522,7 @@ public void selectTreatedParentRootEmbeddableOneToManyListEmbeddable() { @Test public void selectMultipleTreatedParentRootEmbeddableOneToManyListEmbeddable() { + assumeRootTreatJoinSupportedOrEmulated(); List bases = list( from(Object[].class, "Base", "b") .selectSubquery() @@ -532,8 +536,7 @@ public void selectMultipleTreatedParentRootEmbeddableOneToManyListEmbeddable() { .select("SUM(TREAT(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List AS " + strategy + "Sub2).embeddable2.sub2SomeValue)") .end() ); - System.out.println("selectMultipleTreatedParentRootEmbeddableOneToManyListEmbeddable-" + strategy); - + // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 // The sub1Value and sub2Value is doubled diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/AbstractTreatVariationsTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/AbstractTreatVariationsTest.java index 66286083bf..306b4071d8 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/AbstractTreatVariationsTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/AbstractTreatVariationsTest.java @@ -25,14 +25,17 @@ import com.blazebit.persistence.testsuite.treat.entity.Base; import com.blazebit.persistence.testsuite.treat.entity.BaseEmbeddable; import com.blazebit.persistence.testsuite.treat.entity.IntIdEntity; +import com.blazebit.persistence.testsuite.treat.entity.JoinedBase; import com.blazebit.persistence.testsuite.treat.entity.JoinedSub1; import com.blazebit.persistence.testsuite.treat.entity.JoinedSub2; +import com.blazebit.persistence.testsuite.treat.entity.SingleTableBase; import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub1; import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub2; import com.blazebit.persistence.testsuite.treat.entity.Sub1; import com.blazebit.persistence.testsuite.treat.entity.Sub1Embeddable; import com.blazebit.persistence.testsuite.treat.entity.Sub2; import com.blazebit.persistence.testsuite.treat.entity.Sub2Embeddable; +import com.blazebit.persistence.testsuite.treat.entity.TablePerClassBase; import com.blazebit.persistence.testsuite.treat.entity.TablePerClassSub1; import com.blazebit.persistence.testsuite.treat.entity.TablePerClassSub2; import com.blazebit.persistence.testsuite.tx.TxVoidWork; @@ -64,17 +67,17 @@ public AbstractTreatVariationsTest(String strategy, String objectPrefix) { @Override protected Class[] getEntityClasses() { return new Class[] { - Base.class, BaseEmbeddable.class, IntIdEntity.class, + JoinedBase.class, JoinedSub1.class, JoinedSub2.class, + SingleTableBase.class, SingleTableSub1.class, SingleTableSub2.class, - Sub1.class, Sub1Embeddable.class, - Sub2.class, Sub2Embeddable.class, + TablePerClassBase.class, TablePerClassSub1.class, TablePerClassSub2.class }; diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapKeyTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapKeyTest.java deleted file mode 100644 index de43d9f13a..0000000000 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapKeyTest.java +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright 2014 - 2017 Blazebit. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.blazebit.persistence.testsuite.treat.jpql; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.util.List; - -@RunWith(Parameterized.class) -public class JoinManyToManyMapKeyTest extends AbstractTreatVariationsTest { - - public JoinManyToManyMapKeyTest(String strategy, String objectPrefix) { - super(strategy, objectPrefix); - } - - @Parameterized.Parameters - public static Object[] getParameters() { - return new Object[] { - new Object[] { "Joined", "s" }, - new Object[] { "SingleTable", "st" }, - new Object[] { "TablePerClass", "tpc" } - }; - } - - @Test - public void treatJoinManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : - // - SingleTable : - // - TablePerClass : - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(b.map) AS " + strategy + "Sub1) s1", Integer.class); - System.out.println("treatJoinManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : - // - SingleTable : - // - TablePerClass : - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value, s2.sub2Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(b.map) AS " + strategy + "Sub1) s1 LEFT JOIN TREAT(KEY(b.map) AS " + strategy + "Sub2) s2", Object[].class); - System.out.println("treatJoinMultipleManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map) => 4 instances - // Left join on KEY(b.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinParentManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(b.map) AS " + strategy + "Sub1) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("treatJoinParentManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys but only two are Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleParentManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(b.map) AS " + strategy + "Sub1) s1), (SELECT s2.sub2Value FROM TREAT(KEY(b.map) AS " + strategy + "Sub2) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("treatJoinMultipleParentManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys, two are Sub1 and the other are Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : - // - SingleTable : - // - TablePerClass : - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1) s1", Integer.class); - System.out.println("treatJoinEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : - // - SingleTable : - // - TablePerClass : - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value, s2.sub2Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1) s1 LEFT JOIN TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2) s2", Object[].class); - System.out.println("treatJoinMultipleEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - // Left join on KEY(b.embeddable.map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - public void treatJoinParentEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("treatJoinParentEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys but only two are Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 1); - assertRemoved(bases, 101); - } - - @Test - public void treatJoinMultipleParentEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub1) s1), (SELECT s2.sub2Value FROM TREAT(KEY(b.embeddable.map) AS " + strategy + "Sub2) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("treatJoinMultipleParentEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are four map keys, two are Sub1 and the other are Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { 1, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 2 }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, join path parsing fails - // - SingleTable : not working, join path parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.value FROM " + strategy + "Base b LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub1).map1) s1", Integer.class); - System.out.println("joinTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, join path parsing fails - // - SingleTable : not working, join path parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.value, s2.value FROM " + strategy + "Base b LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub1).map1) s1 LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub2).map2) s2", Object[].class); - System.out.println("joinMultipleTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - // Left join on KEY(b.map2) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedParentRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.value FROM KEY(TREAT(b AS " + strategy + "Sub1).map1) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("joinTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedParentRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.value FROM KEY(TREAT(b AS " + strategy + "Sub1).map1) s1), (SELECT s2.value FROM KEY(TREAT(b AS " + strategy + "Sub2).map2) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("joinMultipleTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, join path parsing fails - // - SingleTable : not working, join path parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.value FROM " + strategy + "Base b LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) s1", Integer.class); - System.out.println("joinTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on b.embeddable.sub1Parent => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, join path parsing fails - // - SingleTable : not working, join path parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.value, s2.value FROM " + strategy + "Base b LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) s1 LEFT JOIN KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) s2", Object[].class); - System.out.println("joinMultipleTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - // Left join on KEY(b.embeddable2.sub2Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinTreatedParentRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("joinTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void joinMultipleTreatedParentRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) s1), (SELECT s2.sub2Value FROM KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("joinMultipleTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1) AS s1", Integer.class); - System.out.println("treatJoinTreatedRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value, s2.sub2Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1) AS s1 LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2) AS s2", Object[].class); - System.out.println("treatJoinMultipleTreatedRooManyToManyMapKeyt-" + strategy); - - // From => 4 instances - // Left join on KEY(b.map1) => 4 instances - // Left join on KEY(b.map2) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedParentRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("treatJoinTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedParentRootManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub1).map1) AS " + strategy + "Sub1) s1), (SELECT s2.sub2Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub2).map2) AS " + strategy + "Sub2) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("treatJoinMultipleTreatedParentRootManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1) AS s1", Integer.class); - System.out.println("treatJoinTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, parsing key fails - // - SingleTable : not working, parsing key fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, treated paths unsupported - // - SingleTable : not working, treated paths unsupported - // - TablePerClass : not working, treated paths unsupported - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT s1.sub1Value, s2.sub2Value FROM " + strategy + "Base b LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1) AS s1 LEFT JOIN TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2) AS s2", Object[].class); - System.out.println("treatJoinMultipleTreatedRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // Left join on KEY(b.embeddable1.sub1Map) => 4 instances - // Left join on KEY(b.embeddable2.sub2Map) => 4 instances - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinTreatedParentRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1) s1) FROM " + strategy + "Base b", Integer.class); - System.out.println("treatJoinTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys but only one is Sub1 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, null); - assertRemoved(bases, 101); - } - - @Test - // NOTE: This is a special case that the JPA spec does not cover but is required to make TREAT complete - public void treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapKey() { - // EclipseLink - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, strategy unsupported - // Hibernate - // - Joined : not working, subquery parsing fails - // - SingleTable : not working, subquery parsing fails - // - TablePerClass : not working, subquery parsing fails - // DataNucleus - // - Joined : - // - SingleTable : - // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map) AS " + strategy + "Sub1) s1), (SELECT s2.sub2Value FROM TREAT(KEY(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map) AS " + strategy + "Sub2) s2) FROM " + strategy + "Base b", Object[].class); - System.out.println("treatJoinMultipleTreatedParentRootEmbeddableManyToManyMapKey-" + strategy); - - // From => 4 instances - // There are two map keys, one is Sub1 and the other Sub2 - Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { 101, null }); - assertRemoved(bases, new Object[] { null, 102 }); - } - -} diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapValueTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapValueTest.java index dbf9a31972..83b802135b 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapValueTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToManyMapValueTest.java @@ -272,7 +272,7 @@ public void joinTreatedRootManyToManyMapValue() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -298,8 +298,8 @@ public void joinMultipleTreatedRootManyToManyMapValue() { // Left join on b.map1 => 4 instances // Left join on b.map2 => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -319,7 +319,7 @@ public void joinTreatedParentRootManyToManyMapValue() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).map1 s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).map1 s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootManyToManyMapValue-" + strategy); // From => 4 instances @@ -327,7 +327,7 @@ public void joinTreatedParentRootManyToManyMapValue() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -346,14 +346,14 @@ public void joinMultipleTreatedParentRootManyToManyMapValue() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).map1 s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).map2 s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).map1 s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).map2 s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootManyToManyMapValue-" + strategy); // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -381,7 +381,7 @@ public void joinTreatedRootEmbeddableManyToManyMapValue() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -407,8 +407,8 @@ public void joinMultipleTreatedRootEmbeddableManyToManyMapValue() { // Left join on b.embeddable1.sub1Parent => 4 instances // Left join on b.embeddable2.sub2Parent => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -428,7 +428,7 @@ public void joinTreatedParentRootEmbeddableManyToManyMapValue() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); // From => 4 instances @@ -436,7 +436,7 @@ public void joinTreatedParentRootEmbeddableManyToManyMapValue() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -455,14 +455,14 @@ public void joinMultipleTreatedParentRootEmbeddableManyToManyMapValue() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Map s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Map s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootEmbeddableManyToManyMapValue-" + strategy); // From => 4 instances // There are two map values, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToOneTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToOneTest.java index 50f74edd5a..10da4db3e7 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToOneTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinManyToOneTest.java @@ -428,7 +428,7 @@ public void joinTreatedParentRootEmbeddableManyToOne() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootEmbeddableManyToOne-" + strategy); // From => 4 instances @@ -455,7 +455,7 @@ public void joinMultipleTreatedParentRootEmbeddableManyToOne() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Parent s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Parent s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootEmbeddableManyToOne-" + strategy); // From => 4 instances diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyInverseSetTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyInverseSetTest.java index e9f04807d2..d33fe31ec6 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyInverseSetTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyInverseSetTest.java @@ -319,7 +319,7 @@ public void joinTreatedParentRootOneToManyInverseSet() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).children1 s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).children1 s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootOneToManyInverseSet-" + strategy); // From => 4 instances @@ -346,7 +346,7 @@ public void joinMultipleTreatedParentRootOneToManyInverseSet() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).children1 s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).children2 s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).children1 s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).children2 s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootOneToManyInverseSet-" + strategy); // From => 4 instances @@ -428,7 +428,7 @@ public void joinTreatedParentRootEmbeddableOneToManyInverseSet() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); // From => 4 instances @@ -455,7 +455,7 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1Children s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2Children s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootEmbeddableOneToManyInverseSet-" + strategy); // From => 4 instances diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyListTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyListTest.java index 04807fc456..24cd1ea2c1 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyListTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/JoinOneToManyListTest.java @@ -272,7 +272,7 @@ public void joinTreatedRootOneToManyList() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -298,8 +298,8 @@ public void joinMultipleTreatedRootOneToManyList() { // Left join on b.list1 => 4 instances // Left join on b.list2 => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -319,7 +319,7 @@ public void joinTreatedParentRootOneToManyList() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).list1 s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).list1 s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootOneToManyList-" + strategy); // From => 4 instances @@ -327,7 +327,7 @@ public void joinTreatedParentRootOneToManyList() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -346,14 +346,14 @@ public void joinMultipleTreatedParentRootOneToManyList() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).list1 s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).list2 s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).list1 s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).list2 s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootOneToManyList-" + strategy); // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -381,7 +381,7 @@ public void joinTreatedRootEmbeddableOneToManyList() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -407,8 +407,8 @@ public void joinMultipleTreatedRootEmbeddableOneToManyList() { // Left join on b.embeddable1.sub1List => 4 instances // Left join on b.embeddable2.sub2List => 4 instances Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } @@ -428,7 +428,7 @@ public void joinTreatedParentRootEmbeddableOneToManyList() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List s1) FROM " + strategy + "Base b", Integer.class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List s1) FROM " + strategy + "Base b", Integer.class); System.out.println("joinTreatedParentRootEmbeddableOneToManyList-" + strategy); // From => 4 instances @@ -436,7 +436,7 @@ public void joinTreatedParentRootEmbeddableOneToManyList() { Assert.assertEquals(4, bases.size()); assertRemoved(bases, null); assertRemoved(bases, null); - assertRemoved(bases, null); + assertRemoved(bases, 2); assertRemoved(bases, 101); } @@ -455,14 +455,14 @@ public void joinMultipleTreatedParentRootEmbeddableOneToManyList() { // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT (SELECT s1.sub1Value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List s1), (SELECT s2.sub2Value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List s2) FROM " + strategy + "Base b", Object[].class); + List bases = list("SELECT (SELECT s1.value FROM TREAT(b AS " + strategy + "Sub1).embeddable1.sub1List s1), (SELECT s2.value FROM TREAT(b AS " + strategy + "Sub2).embeddable2.sub2List s2) FROM " + strategy + "Base b", Object[].class); System.out.println("joinMultipleTreatedParentRootEmbeddableOneToManyList-" + strategy); // From => 4 instances // There are two list elements, one is Sub1 and the other Sub2 Assert.assertEquals(4, bases.size()); - assertRemoved(bases, new Object[] { null, null }); - assertRemoved(bases, new Object[] { null, null }); + assertRemoved(bases, new Object[] { 2, null }); + assertRemoved(bases, new Object[] { null, 1 }); assertRemoved(bases, new Object[] { 101, null }); assertRemoved(bases, new Object[] { null, 102 }); } diff --git a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/RootTreatTest.java b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/RootTreatTest.java index 7245e1249c..492516bf6c 100644 --- a/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/RootTreatTest.java +++ b/core/testsuite/src/test/java/com/blazebit/persistence/testsuite/treat/jpql/RootTreatTest.java @@ -252,37 +252,60 @@ public void selectMultipleTreatedParentRootEmbeddableBasic() { assertRemoved(bases, new Object[] { null, 4L }); assertRemoved(bases, new Object[] { null, 204L }); } - + @Test public void whereTreatedRootBasic() { // EclipseLink - // - Joined : issues 1 query, FAILS because filters subtype - // - SingleTable : issues 1 query, FAILS because filters subtype + // - Joined : + // - SingleTable : // - TablePerClass : not working, strategy unsupported // Hibernate // - Joined : not working, treated paths unsupported // - SingleTable : not working, treated paths unsupported // - TablePerClass : not working, treated paths unsupported // DataNucleus + // - Joined : + // - SingleTable : + // - TablePerClass : + List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0) < 100", String.class); + System.out.println("whereTreatedRootBasic-" + strategy); + + // From => 4 instances + // Where => 1 instance because 1 Sub1 has sub1Value 101, the others are Sub2s + Assert.assertEquals(1, bases.size()); + assertRemoved(bases, objectPrefix + "1"); + } + + @Test + public void whereTreatedRootBasicOr() { + // EclipseLink + // - Joined : + // - SingleTable : + // - TablePerClass : + // Hibernate + // - Joined : + // - SingleTable : + // - TablePerClass : + // DataNucleus // - Joined : // - SingleTable : // - TablePerClass : - List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0) < 100", String.class); - System.out.println("whereTreatedRootBasic-" + strategy); + List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE TYPE(b) <> " + strategy + "Sub1 OR COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0) < 100", String.class); + System.out.println("whereTreatedRootBasicOr-" + strategy); // From => 4 instances - // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce + // Where => 3 instance because 1 Sub1 has sub1Value 101, the others are Sub2s Assert.assertEquals(3, bases.size()); - assertRemoved(bases, objectPrefix + "1.parent"); assertRemoved(bases, objectPrefix + "2.parent"); assertRemoved(bases, objectPrefix + "1"); + assertRemoved(bases, objectPrefix + "2"); } @Test public void whereMultipleTreatedRootBasic() { // EclipseLink - // - Joined : issues 1 query, FAILS because filters subtype - // - SingleTable : issues 1 query, FAILS because filters subtype + // - Joined : + // - SingleTable : // - TablePerClass : not working, strategy unsupported // Hibernate // - Joined : not working, treated paths unsupported @@ -296,8 +319,30 @@ public void whereMultipleTreatedRootBasic() { System.out.println("whereMultipleTreatedRootBasic-" + strategy); // From => 4 instances - // Where => 2 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce - // and 1 Sub2 has sub2Value 102, the other has 2 and Sub1 uses 0 because of coalesce + // Where => 0 instances because one variable can't be treated with 2 different subtypes in a single AND predicate + Assert.assertEquals(0, bases.size()); + } + + @Test + public void whereMultipleTreatedRootBasicOr() { + // EclipseLink + // - Joined : + // - SingleTable : + // - TablePerClass : not working, strategy unsupported + // Hibernate + // - Joined : not working, treated paths unsupported + // - SingleTable : not working, treated paths unsupported + // - TablePerClass : not working, treated paths unsupported + // DataNucleus + // - Joined : + // - SingleTable : + // - TablePerClass : + List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE TYPE(b) <> " + strategy + "Sub1 OR COALESCE(TREAT(b AS " + strategy + "Sub1).sub1Value, 0) < 100 AND TYPE(b) <> " + strategy + "Sub2 OR COALESCE(TREAT(b AS " + strategy + "Sub2).sub2Value, 0) < 100", String.class); + System.out.println("whereMultipleTreatedRootBasicOr-" + strategy); + + // From => 4 instances + // Where => 2 instances because 1 Sub1 has sub1Value 101, the other has 1 + // 1 Sub2 has sub2Value 102, the other has 2 Assert.assertEquals(2, bases.size()); assertRemoved(bases, objectPrefix + "1"); assertRemoved(bases, objectPrefix + "2"); @@ -306,8 +351,8 @@ public void whereMultipleTreatedRootBasic() { @Test public void whereTreatedRootEmbeddableBasic() { // EclipseLink - // - Joined : issues 1 query, FAILS because filters subtype - // - SingleTable : issues 1 query, FAILS because filters subtype + // - Joined : + // - SingleTable : // - TablePerClass : not working, strategy unsupported // Hibernate // - Joined : not working, treated paths unsupported @@ -320,19 +365,42 @@ public void whereTreatedRootEmbeddableBasic() { List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0) < 100", String.class); System.out.println("whereTreatedRootEmbeddableBasic-" + strategy); + // From => 4 instances + // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce + Assert.assertEquals(1, bases.size()); + assertRemoved(bases, objectPrefix + "1"); + } + + @Test + public void whereTreatedRootEmbeddableBasicOr() { + // EclipseLink + // - Joined : + // - SingleTable : + // - TablePerClass : not working, strategy unsupported + // Hibernate + // - Joined : not working, treated paths unsupported + // - SingleTable : not working, treated paths unsupported + // - TablePerClass : not working, treated paths unsupported + // DataNucleus + // - Joined : + // - SingleTable : + // - TablePerClass : + List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE TYPE(b) <> " + strategy + "Sub1 OR COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0) < 100", String.class); + System.out.println("whereTreatedRootEmbeddableBasicOr-" + strategy); + // From => 4 instances // Where => 3 instances because 1 Sub1 has sub1Value 101, the other has 1 and Sub2s use 0 because of coalesce Assert.assertEquals(3, bases.size()); - assertRemoved(bases, objectPrefix + "1.parent"); assertRemoved(bases, objectPrefix + "2.parent"); assertRemoved(bases, objectPrefix + "1"); + assertRemoved(bases, objectPrefix + "2"); } @Test public void whereMultipleTreatedRootEmbeddableBasic() { // EclipseLink - // - Joined : issues 1 query, FAILS because filters subtype - // - SingleTable : issues 1 query, FAILS because filters subtype + // - Joined : + // - SingleTable : // - TablePerClass : not working, strategy unsupported // Hibernate // - Joined : not working, treated paths unsupported @@ -346,8 +414,29 @@ public void whereMultipleTreatedRootEmbeddableBasic() { System.out.println("whereMultipleTreatedRootEmbeddableBasic-" + strategy); // From => 4 instances - // Where => 2 instances because 1 Sub1 has sub1SomeValue 101, the other has 1 and Sub2s use 0 because of coalesce - // and 1 Sub2 has sub2SomeValue 102, the other has 2 and Sub1 uses 0 because of coalesce + // Where => 0 instances because one variable can't be treated with 2 different subtypes in a single AND predicate + Assert.assertEquals(0, bases.size()); + } + + @Test + public void whereMultipleTreatedRootEmbeddableBasicOr() { + // EclipseLink + // - Joined : + // - SingleTable : + // - TablePerClass : not working, strategy unsupported + // Hibernate + // - Joined : not working, treated paths unsupported + // - SingleTable : not working, treated paths unsupported + // - TablePerClass : not working, treated paths unsupported + // DataNucleus + // - Joined : + // - SingleTable : + // - TablePerClass : + List bases = list("SELECT b.name FROM " + strategy + "Base b WHERE TYPE(b) <> " + strategy + "Sub1 OR COALESCE(TREAT(b AS " + strategy + "Sub1).embeddable1.sub1SomeValue, 0) < 100 AND TYPE(b) <> " + strategy + "Sub2 OR COALESCE(TREAT(b AS " + strategy + "Sub2).embeddable2.sub2SomeValue, 0) < 100", String.class); + System.out.println("whereMultipleTreatedRootEmbeddableBasicOr-" + strategy); + + // From => 4 instances + // 1 Sub2 has sub2SomeValue 102, the other has 2 Assert.assertEquals(2, bases.size()); assertRemoved(bases, objectPrefix + "1"); assertRemoved(bases, objectPrefix + "2"); diff --git a/integration/datanucleus/src/main/java/com/blazebit/persistence/impl/datanucleus/DataNucleusJpaProvider.java b/integration/datanucleus/src/main/java/com/blazebit/persistence/impl/datanucleus/DataNucleusJpaProvider.java index 341178b61f..049805d540 100644 --- a/integration/datanucleus/src/main/java/com/blazebit/persistence/impl/datanucleus/DataNucleusJpaProvider.java +++ b/integration/datanucleus/src/main/java/com/blazebit/persistence/impl/datanucleus/DataNucleusJpaProvider.java @@ -134,7 +134,9 @@ public String getCustomFunctionInvocation(String functionName, int argumentCount @Override public boolean supportsRootTreat() { - return true; + // Although it might parse, it isn't really supported for JOINED inheritance as wrong SQL is generated + // TODO: create an issue for this + return false; } @Override @@ -142,24 +144,40 @@ public boolean supportsTreatJoin() { return major >= 5; } + @Override + public boolean supportsTreatCorrelation() { + return false; + } + @Override public boolean supportsRootTreatJoin() { return false; } + @Override + public boolean supportsRootTreatTreatJoin() { + return false; + } + @Override public boolean supportsSubtypePropertyResolving() { return false; } + @Override + public boolean supportsSubtypeRelationResolving() { + // Interestingly, joining a relation that is only available on a subtype works + return true; + } + @Override public boolean supportsCountStar() { return false; } @Override - public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeName) { - ManagedTypeImpl managedType = (ManagedTypeImpl) ownerClass; + public boolean isForeignJoinColumn(ManagedType ownerType, String attributeName) { + ManagedTypeImpl managedType = (ManagedTypeImpl) ownerType; String[] parts = attributeName.split("\\."); AbstractMemberMetaData metaData = managedType.getMetadata().getMetaDataForMember(parts[0]); for (int i = 1; i < parts.length; i++) { @@ -181,6 +199,11 @@ public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeNa return metaData.getJoinMetaData() != null; } + @Override + public boolean isColumnShared(ManagedType ownerType, String attributeName) { + return false; + } + @Override public boolean isJoinTable(Attribute attribute) { AbstractMemberMetaData metaData = ((AttributeImpl) attribute).getMetadata(); @@ -225,4 +248,9 @@ public boolean needsAssociationToIdRewriteInOnClause() { public boolean needsBrokenAssociationToIdRewriteInOnClause() { return false; } + + @Override + public boolean needsTypeConstraintForColumnSharing() { + return false; + } } diff --git a/integration/eclipselink/src/main/java/com/blazebit/persistence/impl/eclipselink/EclipseLinkJpaProvider.java b/integration/eclipselink/src/main/java/com/blazebit/persistence/impl/eclipselink/EclipseLinkJpaProvider.java index 302d9293d8..7879f99cf0 100644 --- a/integration/eclipselink/src/main/java/com/blazebit/persistence/impl/eclipselink/EclipseLinkJpaProvider.java +++ b/integration/eclipselink/src/main/java/com/blazebit/persistence/impl/eclipselink/EclipseLinkJpaProvider.java @@ -141,9 +141,19 @@ public boolean supportsTreatJoin() { return true; } + @Override + public boolean supportsTreatCorrelation() { + return false; + } + @Override public boolean supportsRootTreatJoin() { - return true; + return false; + } + + @Override + public boolean supportsRootTreatTreatJoin() { + return false; } @Override @@ -151,14 +161,19 @@ public boolean supportsSubtypePropertyResolving() { return false; } + @Override + public boolean supportsSubtypeRelationResolving() { + return false; + } + @Override public boolean supportsCountStar() { return false; } @Override - public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeName) { - ManagedTypeImpl managedType = (ManagedTypeImpl) ownerClass; + public boolean isForeignJoinColumn(ManagedType ownerType, String attributeName) { + ManagedTypeImpl managedType = (ManagedTypeImpl) ownerType; String[] parts = attributeName.split("\\."); DatabaseMapping mapping = managedType.getDescriptor().getMappingForAttributeName(parts[0]); for (int i = 1; i < parts.length; i++) { @@ -170,6 +185,11 @@ public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeNa return false; } + @Override + public boolean isColumnShared(ManagedType ownerType, String attributeName) { + return false; + } + @Override public boolean isJoinTable(Attribute attribute) { DatabaseMapping mapping = ((AttributeImpl) attribute).getMapping(); @@ -223,4 +243,9 @@ public boolean needsBrokenAssociationToIdRewriteInOnClause() { return false; } + @Override + public boolean needsTypeConstraintForColumnSharing() { + return false; + } + } diff --git a/integration/hibernate-base/src/main/java/com/blazebit/persistence/impl/hibernate/HibernateJpaProvider.java b/integration/hibernate-base/src/main/java/com/blazebit/persistence/impl/hibernate/HibernateJpaProvider.java index 70f519323b..90330f7ed9 100644 --- a/integration/hibernate-base/src/main/java/com/blazebit/persistence/impl/hibernate/HibernateJpaProvider.java +++ b/integration/hibernate-base/src/main/java/com/blazebit/persistence/impl/hibernate/HibernateJpaProvider.java @@ -22,6 +22,9 @@ import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Joinable; +import org.hibernate.persister.entity.SingleTableEntityPersister; +import org.hibernate.persister.entity.UnionSubclassEntityPersister; +import org.hibernate.type.ComponentType; import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.OneToOneType; import org.hibernate.type.Type; @@ -30,7 +33,12 @@ import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.PluralAttribute; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * @@ -42,6 +50,7 @@ public class HibernateJpaProvider implements JpaProvider { private final DB db; private final Map entityPersisters; private final Map collectionPersisters; + private final ConcurrentMap columnSharingCache = new ConcurrentHashMap<>(); private static enum DB { OTHER, @@ -214,24 +223,39 @@ public boolean supportsTreatJoin() { return false; } + @Override + public boolean supportsTreatCorrelation() { + return false; + } + @Override public boolean supportsRootTreatJoin() { return false; } + @Override + public boolean supportsRootTreatTreatJoin() { + return false; + } + @Override public boolean supportsSubtypePropertyResolving() { return true; } + @Override + public boolean supportsSubtypeRelationResolving() { + return true; + } + @Override public boolean supportsCountStar() { return true; } @Override - public boolean isForeignJoinColumn(ManagedType managedType, String attributeName) { - AbstractEntityPersister persister = (AbstractEntityPersister) entityPersisters.get(managedType.getJavaType().getName()); + public boolean isForeignJoinColumn(ManagedType ownerType, String attributeName) { + AbstractEntityPersister persister = (AbstractEntityPersister) entityPersisters.get(ownerType.getJavaType().getName()); Type propertyType = persister.getPropertyType(attributeName); if (propertyType instanceof OneToOneType) { @@ -245,6 +269,67 @@ public boolean isForeignJoinColumn(ManagedType managedType, String attributeN return tableNumber >= persister.getEntityMetamodel().getSubclassEntityNames().size(); } + @Override + public boolean isColumnShared(ManagedType ownerType, String attributeName) { + AbstractEntityPersister persister = (AbstractEntityPersister) entityPersisters.get(ownerType.getJavaType().getName()); + if (!(persister instanceof SingleTableEntityPersister) && !(persister instanceof UnionSubclassEntityPersister)) { + return false; + } + + ColumnSharingCacheKey cacheKey = new ColumnSharingCacheKey(ownerType, attributeName); + Boolean result = columnSharingCache.get(cacheKey); + if (result != null) { + return result; + } + + if (persister instanceof SingleTableEntityPersister) { + SingleTableEntityPersister singleTableEntityPersister = (SingleTableEntityPersister) persister; + SingleTableEntityPersister rootPersister = (SingleTableEntityPersister) entityPersisters.get(singleTableEntityPersister.getRootEntityName()); + result = isColumnShared(singleTableEntityPersister, rootPersister.getName(), rootPersister.getSubclassClosure(), attributeName); + } else if (persister instanceof UnionSubclassEntityPersister) { + UnionSubclassEntityPersister unionSubclassEntityPersister = (UnionSubclassEntityPersister) persister; + UnionSubclassEntityPersister rootPersister = (UnionSubclassEntityPersister) entityPersisters.get(unionSubclassEntityPersister.getRootEntityName()); + result = isColumnShared(unionSubclassEntityPersister, rootPersister.getName(), rootPersister.getSubclassClosure(), attributeName); + } + + columnSharingCache.put(cacheKey, result); + return result; + } + + private boolean isColumnShared(AbstractEntityPersister persister, String rootName, String[] subclassNames, String attributeName) { + String[] columnNames = persister.getSubclassPropertyColumnNames(attributeName); + for (String subclass: subclassNames) { + if (!subclass.equals(persister.getName()) && !subclass.equals(rootName)) { + AbstractEntityPersister subclassPersister = (AbstractEntityPersister) entityPersisters.get(subclass); + if (isColumnShared(subclassPersister, columnNames)) { + return true; + } + } + } + return false; + } + + private boolean isColumnShared(AbstractEntityPersister subclassPersister, String[] columnNames) { + List propertiesToCheck = new ArrayList<>(Arrays.asList(subclassPersister.getPropertyNames())); + while (!propertiesToCheck.isEmpty()) { + String propertyName = propertiesToCheck.remove(propertiesToCheck.size() - 1); + Type propertyType = subclassPersister.getPropertyType(propertyName); + if (propertyType instanceof ComponentType) { + ComponentType componentType = (ComponentType) propertyType; + for (String subPropertyName : componentType.getPropertyNames()) { + propertiesToCheck.add(propertyName + "." + subPropertyName); + } + } else { + String[] subclassColumnNames = subclassPersister.getSubclassPropertyColumnNames(propertyName); + if (Arrays.deepEquals(columnNames, subclassColumnNames)) { + return true; + } + } + } + + return false; + } + @Override public boolean isJoinTable(Attribute attribute) { StringBuilder sb = new StringBuilder(200); @@ -307,4 +392,44 @@ public boolean needsAssociationToIdRewriteInOnClause() { public boolean needsBrokenAssociationToIdRewriteInOnClause() { return true; } + + @Override + public boolean needsTypeConstraintForColumnSharing() { + return true; + } + + private static class ColumnSharingCacheKey { + private final ManagedType managedType; + private final String attributeName; + + public ColumnSharingCacheKey(ManagedType managedType, String attributeName) { + this.managedType = managedType; + this.attributeName = attributeName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ColumnSharingCacheKey that = (ColumnSharingCacheKey) o; + + if (!managedType.equals(that.managedType)) { + return false; + } + return attributeName.equals(that.attributeName); + } + + @Override + public int hashCode() { + int result = managedType.hashCode(); + result = 31 * result + attributeName.hashCode(); + return result; + } + } + } diff --git a/integration/openjpa/src/main/java/com/blazebit/persistence/impl/openjpa/OpenJPAJpaProvider.java b/integration/openjpa/src/main/java/com/blazebit/persistence/impl/openjpa/OpenJPAJpaProvider.java index 21fc3a1570..d8702efb56 100644 --- a/integration/openjpa/src/main/java/com/blazebit/persistence/impl/openjpa/OpenJPAJpaProvider.java +++ b/integration/openjpa/src/main/java/com/blazebit/persistence/impl/openjpa/OpenJPAJpaProvider.java @@ -118,27 +118,47 @@ public boolean supportsTreatJoin() { return false; } + @Override + public boolean supportsTreatCorrelation() { + return false; + } + @Override public boolean supportsRootTreatJoin() { return false; } + @Override + public boolean supportsRootTreatTreatJoin() { + return false; + } + @Override public boolean supportsSubtypePropertyResolving() { return false; } + @Override + public boolean supportsSubtypeRelationResolving() { + return false; + } + @Override public boolean supportsCountStar() { return false; } @Override - public boolean isForeignJoinColumn(ManagedType ownerClass, String attributeName) { + public boolean isForeignJoinColumn(ManagedType ownerType, String attributeName) { // just return true since we don't need that for openjpa anyway return true; } + @Override + public boolean isColumnShared(ManagedType ownerType, String attributeName) { + return false; + } + @Override public boolean isJoinTable(Attribute attribute) { // just return false since we don't need that for openjpa anyway @@ -174,4 +194,9 @@ public boolean needsAssociationToIdRewriteInOnClause() { public boolean needsBrokenAssociationToIdRewriteInOnClause() { return false; } + + @Override + public boolean needsTypeConstraintForColumnSharing() { + return false; + } } diff --git a/parent/pom.xml b/parent/pom.xml index 0522aa44b7..5612bcc791 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -66,7 +66,7 @@ 6.0-4 - 2.2.4 + 3.2.0 1.0.2 2.5.1 2.19.1 diff --git a/testsuite-base/datanucleus/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java b/testsuite-base/datanucleus/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java index c2cbc723e5..cf4aca19dc 100644 --- a/testsuite-base/datanucleus/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java +++ b/testsuite-base/datanucleus/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java @@ -37,6 +37,16 @@ protected Properties applyProperties(Properties properties) { return properties; } + @Override + protected boolean supportsMapKeyDeReference() { + return true; + } + + @Override + protected boolean supportsInverseSetCorrelationJoinsSubtypesWhenJoined() { + return true; + } + @Override protected Connection getConnection(EntityManager em) { return (Connection) em.unwrap(StoreManager.class).getConnection(em.unwrap(ExecutionContext.class)).getConnection(); diff --git a/testsuite-base/eclipselink/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java b/testsuite-base/eclipselink/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java index 2cb6d1235d..0d35b851f6 100644 --- a/testsuite-base/eclipselink/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java +++ b/testsuite-base/eclipselink/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java @@ -48,6 +48,16 @@ protected Properties applyProperties(Properties properties) { return properties; } + @Override + protected boolean supportsMapKeyDeReference() { + return true; + } + + @Override + protected boolean supportsInverseSetCorrelationJoinsSubtypesWhenJoined() { + return true; + } + @Override protected void addIgnores(DatabaseCleaner applicableCleaner) { applicableCleaner.addIgnoredTable("SEQUENCE"); @@ -88,7 +98,7 @@ protected void dropSchema() { } } - protected void dropAndCreateSchema() { + protected void recreateOrClearSchema() { Map emSetupImpls = EntityManagerFactoryProvider.getEmSetupImpls(); Map copy = new HashMap<>(emSetupImpls); emSetupImpls.clear(); @@ -97,7 +107,7 @@ protected void dropAndCreateSchema() { manager.getSessions().remove(emSetupImpl.getSessionName()); } try { - super.dropAndCreateSchema(); + super.recreateOrClearSchema(); } finally { emSetupImpls.putAll(copy); for (EntityManagerSetupImpl emSetupImpl : copy.values()) { diff --git a/testsuite-base/hibernate/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java b/testsuite-base/hibernate/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java index 8de9a8adac..d3ff1b8f08 100644 --- a/testsuite-base/hibernate/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java +++ b/testsuite-base/hibernate/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java @@ -65,12 +65,12 @@ protected Properties applyProperties(Properties properties) { } } - if (isHibernate42()) { - properties.put("hibernate.connection.url", properties.get("javax.persistence.jdbc.url")); - properties.put("hibernate.connection.password", properties.get("javax.persistence.jdbc.password")); - properties.put("hibernate.connection.username", properties.get("javax.persistence.jdbc.user")); - properties.put("hibernate.connection.driver_class", properties.get("javax.persistence.jdbc.driver")); - String dbAction = (String) properties.get("javax.persistence.schema-generation.database.action"); + if (useHbm2ddl()) { + properties.put("hibernate.connection.url", properties.remove("javax.persistence.jdbc.url")); + properties.put("hibernate.connection.password", properties.remove("javax.persistence.jdbc.password")); + properties.put("hibernate.connection.username", properties.remove("javax.persistence.jdbc.user")); + properties.put("hibernate.connection.driver_class", properties.remove("javax.persistence.jdbc.driver")); + String dbAction = (String) properties.remove("javax.persistence.schema-generation.database.action"); if ("drop-and-create".equals(dbAction)) { properties.put("hibernate.hbm2ddl.auto", "create"); } else if ("create".equals(dbAction)) { @@ -97,12 +97,32 @@ protected Properties applyProperties(Properties properties) { return properties; } - private boolean isHibernate42() { + @Override + protected boolean supportsMapKeyDeReference() { + // Only got introduced in 5.2.8 + String version = org.hibernate.Version.getVersionString(); + String[] versionParts = version.split("\\."); + int major = Integer.parseInt(versionParts[0]); + int minor = Integer.parseInt(versionParts[1]); + int fix = Integer.parseInt(versionParts[2]); + return major > 5 || major == 5 && minor > 2 || major == 5 && minor == 2 && fix > 7; + } + + @Override + protected boolean supportsInverseSetCorrelationJoinsSubtypesWhenJoined() { + // Apparently this got fixed in Hibernate 5 + String version = org.hibernate.Version.getVersionString(); + String[] versionParts = version.split("\\."); + int major = Integer.parseInt(versionParts[0]); + return major >= 5; + } + + private boolean useHbm2ddl() { String version = org.hibernate.Version.getVersionString(); String[] versionParts = version.split("\\."); int major = Integer.parseInt(versionParts[0]); int minor = Integer.parseInt(versionParts[1]); - return major == 4 && minor == 2; + return major == 4 && minor <= 3; } private boolean isHibernate5() { diff --git a/testsuite-base/jpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractJpaPersistenceTest.java b/testsuite-base/jpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractJpaPersistenceTest.java index 926fa9ba4e..3f1036bba2 100644 --- a/testsuite-base/jpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractJpaPersistenceTest.java +++ b/testsuite-base/jpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractJpaPersistenceTest.java @@ -43,6 +43,8 @@ import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; +import com.blazebit.persistence.spi.JpaProvider; +import com.blazebit.persistence.spi.JpaProviderFactory; import com.blazebit.persistence.testsuite.base.cleaner.DB2DatabaseCleaner; import com.blazebit.persistence.testsuite.base.cleaner.DatabaseCleaner; import com.blazebit.persistence.testsuite.base.cleaner.H2DatabaseCleaner; @@ -77,6 +79,7 @@ public abstract class AbstractJpaPersistenceTest { protected EntityManagerFactory emf; protected EntityManager em; protected CriteriaBuilderFactory cbf; + protected JpaProvider jpaProvider; private boolean schemaChanged; @@ -227,39 +230,48 @@ public void addIgnoredTable(String tableName) { @Override public void clearData(Connection connection) { - dropAndCreateSchema(); + recreateOrClearSchema(); } }); } + CriteriaBuilderConfiguration config = Criteria.getDefault(); + config = configure(config); + cbf = config.createCriteriaBuilderFactory(emf); + jpaProvider = cbf.getService(JpaProviderFactory.class).createJpaProvider(em); + if (schemaChanged || !databaseCleaner.supportsClearSchema()) { - dropAndCreateSchema(); + recreateOrClearSchema(); setUpOnce(); } else if (firstTest) { setUpOnce(); } em.getTransaction().begin(); - - CriteriaBuilderConfiguration config = Criteria.getDefault(); - config = configure(config); - cbf = config.createCriteriaBuilderFactory(emf); } protected void addIgnores(DatabaseCleaner applicableCleaner) { // No-op } + protected void createSchema() { + createEntityManagerFactory("TestsuiteBase", createProperties("create")).close(); + } + protected void dropSchema() { createEntityManagerFactory("TestsuiteBase", createProperties("drop")).close(); } protected void dropAndCreateSchema() { + createEntityManagerFactory("TestsuiteBase", createProperties("drop-and-create")).close(); + } + + protected void recreateOrClearSchema() { if (databaseCleaner.supportsClearSchema()) { clearSchema(); - createEntityManagerFactory("TestsuiteBase", createProperties("create")).close(); + createSchema(); } else { - createEntityManagerFactory("TestsuiteBase", createProperties("drop-and-create")).close(); + dropAndCreateSchema(); } } @@ -267,6 +279,10 @@ protected void setUpOnce() { // No-op } + protected abstract boolean supportsMapKeyDeReference(); + + protected abstract boolean supportsInverseSetCorrelationJoinsSubtypesWhenJoined(); + @After public void destruct() { EntityManagerFactory factory; diff --git a/testsuite-base/openjpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java b/testsuite-base/openjpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java index 5373475268..346e67205f 100644 --- a/testsuite-base/openjpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java +++ b/testsuite-base/openjpa/src/main/java/com/blazebit/persistence/testsuite/base/AbstractPersistenceTest.java @@ -34,4 +34,14 @@ protected Properties applyProperties(Properties properties) { return properties; } + @Override + protected boolean supportsMapKeyDeReference() { + return true; + } + + @Override + protected boolean supportsInverseSetCorrelationJoinsSubtypesWhenJoined() { + return true; + } + }