From b8361df1cbd917af34848b3419e87fd770836341 Mon Sep 17 00:00:00 2001 From: Ajay Paul Date: Tue, 29 Oct 2024 16:25:35 +0530 Subject: [PATCH 1/2] Fix for issue 2211 --- .../jpql/JPQLFunctionsAbstractBuilder.java | 86 ++++++++++++++----- .../internal/jpa/jpql/ReportItemBuilder.java | 3 +- 2 files changed, 66 insertions(+), 23 deletions(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java index 90e3c118458..ac0dbb9f067 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java @@ -28,10 +28,14 @@ import java.util.List; /** - * JPQL exclusive ID(), VERSION() functions/expressions are transformed there to StateFieldPathExpression. - * It should be used in the future for another JPQL functions/expressions which are not available at the DB level. - * E.g. For Entity e with idAttr as a primary key: SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e - * For Entity e with versionAttr as a version attribute: SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e + * JPQL exclusive ID(), VERSION() functions/expressions are transformed there to + * StateFieldPathExpression. + * It should be used in the future for another JPQL functions/expressions which + * are not available at the DB level. + * E.g. For Entity e with idAttr as a primary key: + * SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e + * For Entity e with versionAttr as a version attribute: + * SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e * * @author Radek Felcman * @since 5.0 @@ -39,7 +43,8 @@ public abstract class JPQLFunctionsAbstractBuilder extends EclipseLinkAnonymousExpressionVisitor { /** - * The {@link JPQLQueryContext} is used to query information about the application metadata and + * The {@link JPQLQueryContext} is used to query information about the + * application metadata and * cached information. */ final JPQLQueryContext queryContext; @@ -49,57 +54,94 @@ protected JPQLFunctionsAbstractBuilder(JPQLQueryContext queryContext) { } /** - * For Entity e with idAttr as a primary key: SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e + * For Entity e with idAttr as a primary key: + * SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e * * @param expression The {@link IdExpression} to visit */ @Override public void visit(IdExpression expression) { - //Fetch identification variable info + System.out.println("INSIDE VISIT *******"); IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression(); String variableText = identificationVariable.getText(); String variableName = identificationVariable.getVariableName(); - - //Get id attribute name + // Get id attribute name ClassDescriptor descriptor = this.queryContext.getDeclaration(variableName).getDescriptor(); List primaryKeyFields = descriptor.getPrimaryKeyFields(); - String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyFields.get(0)); - StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), variableText + "." + idAttributeName); - expression.setStateFieldPathExpression(stateFieldPathExpression); + // String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), + // primaryKeyFields.get(0)); + // StateFieldPathExpression stateFieldPathExpression = new + // StateFieldPathExpression(expression.getParent(), variableText + "." + + // idAttributeName); + // expression.setStateFieldPathExpression(stateFieldPathExpression); + // expression.getStateFieldPathExpression().accept(this); + if (!isEmbeddable(descriptor.getMappings())) { + for (DatabaseField primaryKeyField : primaryKeyFields) { + String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyField); + StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression( + expression.getParent(), variableText + "." + idAttributeName); + expression.setStateFieldPathExpression(stateFieldPathExpression); + // Continue with created StateFieldPathExpression + // It handle by ObjectBuilder booth @Id/primary key types (simple/composite) + expression.getStateFieldPathExpression().accept(this); + } + } else { + String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyFields.get(0)); + StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression( + expression.getParent(), variableText + "." + idAttributeName); + expression.setStateFieldPathExpression(stateFieldPathExpression); + // Continue with created StateFieldPathExpression + // It handle by ObjectBuilder booth @Id/primary key types (simple/composite) + expression.getStateFieldPathExpression().accept(this); - //Continue with created StateFieldPathExpression - //It handle by ObjectBuilder booth @Id/primary key types (simple/composite) - expression.getStateFieldPathExpression().accept(this); + } } /** - * For Entity e with versionAttr as a version attribute: SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e + * For Entity e with versionAttr as a version attribute: + * SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e * * @param expression The {@link VersionExpression} to visit */ @Override public void visit(VersionExpression expression) { - //Fetch identification variable info + // Fetch identification variable info IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression(); String variableText = identificationVariable.getText(); String variableName = identificationVariable.getVariableName(); - //Get version attribute name + // Get version attribute name ClassDescriptor descriptor = this.queryContext.getDeclaration(variableName).getDescriptor(); - String versionAttributeName = ((VersionLockingPolicy) descriptor.getOptimisticLockingPolicy()).getVersionMapping().getAttributeName(); - StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), variableText + "." + versionAttributeName); + String versionAttributeName = ((VersionLockingPolicy) descriptor.getOptimisticLockingPolicy()) + .getVersionMapping().getAttributeName(); + StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), + variableText + "." + versionAttributeName); expression.setStateFieldPathExpression(stateFieldPathExpression); - //Continue with created StateFieldPathExpression + // Continue with created StateFieldPathExpression expression.getStateFieldPathExpression().accept(this); } private String getIdAttributeNameByField(List databaseMappings, DatabaseField field) { for (DatabaseMapping mapping : databaseMappings) { - if (field.equals(mapping.getField()) || mapping.isPrimaryKeyMapping()) { + if (mapping.getFields().size() > 1 && (field.equals(mapping.getField()) || mapping.isPrimaryKeyMapping())) { return mapping.getAttributeName(); + } else { + if ((field.equals(mapping.getField()) && mapping.isPrimaryKeyMapping())) { + return mapping.getAttributeName(); + } } } return null; } + + private boolean isEmbeddable(List databaseMappings) { + + for (DatabaseMapping databaseMapping : databaseMappings) { + if (databaseMapping.isPrimaryKeyMapping() && databaseMapping.getFields().size() > 1) { + return true; + } + } + return false; + } } diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/ReportItemBuilder.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/ReportItemBuilder.java index 0e78b8e05d0..6d23c32ddd8 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/ReportItemBuilder.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/ReportItemBuilder.java @@ -41,6 +41,7 @@ import org.eclipse.persistence.jpa.jpql.parser.EntryExpression; import org.eclipse.persistence.jpa.jpql.parser.ExtractExpression; import org.eclipse.persistence.jpa.jpql.parser.FunctionExpression; +import org.eclipse.persistence.jpa.jpql.parser.IdExpression; import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable; import org.eclipse.persistence.jpa.jpql.parser.IndexExpression; import org.eclipse.persistence.jpa.jpql.parser.Join; @@ -630,7 +631,7 @@ private void visitAbstractSelectClause(AbstractSelectClause expression) { multipleSelects = false; expression.getSelectExpression().accept(this); - if (multipleSelects) { + if (multipleSelects || (expression.getSelectExpression() instanceof IdExpression)) { query.returnWithoutReportQueryResult(); } else { From a604ea83d0a6c78b8d0a19de3458656f7a60572a Mon Sep 17 00:00:00 2001 From: Ajay Paul Date: Fri, 8 Nov 2024 12:24:12 +0530 Subject: [PATCH 2/2] Added condition for embeddable --- .../jpql/JPQLFunctionsAbstractBuilder.java | 45 +++++++------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java index ac0dbb9f067..c96960a0573 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/jpa/jpql/JPQLFunctionsAbstractBuilder.java @@ -28,14 +28,10 @@ import java.util.List; /** - * JPQL exclusive ID(), VERSION() functions/expressions are transformed there to - * StateFieldPathExpression. - * It should be used in the future for another JPQL functions/expressions which - * are not available at the DB level. - * E.g. For Entity e with idAttr as a primary key: - * SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e - * For Entity e with versionAttr as a version attribute: - * SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e + * JPQL exclusive ID(), VERSION() functions/expressions are transformed there to StateFieldPathExpression. + * It should be used in the future for another JPQL functions/expressions which are not available at the DB level. + * E.g. For Entity e with idAttr as a primary key: SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e + * For Entity e with versionAttr as a version attribute: SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e * * @author Radek Felcman * @since 5.0 @@ -43,8 +39,7 @@ public abstract class JPQLFunctionsAbstractBuilder extends EclipseLinkAnonymousExpressionVisitor { /** - * The {@link JPQLQueryContext} is used to query information about the - * application metadata and + * The {@link JPQLQueryContext} is used to query information about the application metadata and * cached information. */ final JPQLQueryContext queryContext; @@ -54,27 +49,20 @@ protected JPQLFunctionsAbstractBuilder(JPQLQueryContext queryContext) { } /** - * For Entity e with idAttr as a primary key: - * SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e + * For Entity e with idAttr as a primary key: SELECT ID(e) FROM Entity e -> SELECT e.idAttr FROM Entity e * * @param expression The {@link IdExpression} to visit */ @Override public void visit(IdExpression expression) { - System.out.println("INSIDE VISIT *******"); + //Fetch identification variable info IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression(); String variableText = identificationVariable.getText(); String variableName = identificationVariable.getVariableName(); - // Get id attribute name + + //Get id attribute name ClassDescriptor descriptor = this.queryContext.getDeclaration(variableName).getDescriptor(); List primaryKeyFields = descriptor.getPrimaryKeyFields(); - // String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), - // primaryKeyFields.get(0)); - // StateFieldPathExpression stateFieldPathExpression = new - // StateFieldPathExpression(expression.getParent(), variableText + "." + - // idAttributeName); - // expression.setStateFieldPathExpression(stateFieldPathExpression); - // expression.getStateFieldPathExpression().accept(this); if (!isEmbeddable(descriptor.getMappings())) { for (DatabaseField primaryKeyField : primaryKeyFields) { String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyField); @@ -98,27 +86,24 @@ public void visit(IdExpression expression) { } /** - * For Entity e with versionAttr as a version attribute: - * SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e + * For Entity e with versionAttr as a version attribute: SELECT VERSION(e) FROM Entity e -> SELECT e.versionAttr FROM Entity e * * @param expression The {@link VersionExpression} to visit */ @Override public void visit(VersionExpression expression) { - // Fetch identification variable info + //Fetch identification variable info IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression(); String variableText = identificationVariable.getText(); String variableName = identificationVariable.getVariableName(); - // Get version attribute name + //Get version attribute name ClassDescriptor descriptor = this.queryContext.getDeclaration(variableName).getDescriptor(); - String versionAttributeName = ((VersionLockingPolicy) descriptor.getOptimisticLockingPolicy()) - .getVersionMapping().getAttributeName(); - StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), - variableText + "." + versionAttributeName); + String versionAttributeName = ((VersionLockingPolicy) descriptor.getOptimisticLockingPolicy()).getVersionMapping().getAttributeName(); + StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), variableText + "." + versionAttributeName); expression.setStateFieldPathExpression(stateFieldPathExpression); - // Continue with created StateFieldPathExpression + //Continue with created StateFieldPathExpression expression.getStateFieldPathExpression().accept(this); }