You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2010/01/14 17:21:03 UTC
svn commit: r899270 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src:
main/java/org/apache/cayenne/access/jdbc/
test/java/org/apache/cayenne/access/
Author: aadamchik
Date: Thu Jan 14 16:21:02 2010
New Revision: 899270
URL: http://svn.apache.org/viewvc?rev=899270&view=rev
Log:
CAY-1069 EJBQL: support paths across flattened relationships
patch by Ksenia Khailenko - flattened attributes
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectColumnsTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java?rev=899270&r1=899269&r2=899270&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java Thu Jan 14 16:21:02 2010
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.access.jdbc;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -32,6 +33,9 @@
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.query.EntityResultSegment;
+import org.apache.cayenne.util.CayenneMapEntry;
/**
* Handles appending joins to the content buffer at a marked position.
@@ -226,6 +230,7 @@
public String appendTable(EJBQLTableId id) {
DbEntity dbEntity = id.getDbEntity(context);
+
String tableName = dbEntity.getFullyQualifiedName();
String alias;
@@ -233,11 +238,14 @@
// TODO: andrus 1/5/2007 - if the same table is joined more than once, this
// will create an incorrect alias.
alias = context.getTableAlias(id.getEntityId(), tableName);
-
+
// not using "AS" to separate table name and alias name - OpenBase doesn't
// support
// "AS", and the rest of the databases do not care
context.append(' ').append(tableName).append(' ').append(alias);
+
+ generateJoinsForFlattenedAttributes(id, alias);
+
}
else {
context.append(' ').append(tableName);
@@ -274,6 +282,71 @@
return alias;
}
+ /**
+ * Generates Joins statements for those flattened attributes that appear after the
+ * FROM clause, e.g. in WHERE, ORDER BY, etc clauses. Flattened attributes of the
+ * entity from the SELECT clause are processed earlier and therefore are omitted.
+ *
+ * @param id table to JOIN id
+ * @param alias table alias
+ */
+ private void generateJoinsForFlattenedAttributes(EJBQLTableId id, String alias) {
+ String entityName = context
+ .getEntityDescriptor(id.getEntityId())
+ .getEntity()
+ .getName();
+ boolean isProcessingOmitted = false;
+ // if the dbPath is not null, all attributes of the entity are processed earlier
+ isProcessingOmitted = id.getDbPath() != null;
+ String sourceExpression = context.getCompiledExpression().getSource();
+
+ List<Object> resultSetMapping = context.getMetadata().getResultSetMapping();
+ for (Object mapping : resultSetMapping) {
+ if (mapping instanceof EntityResultSegment) {
+ if (entityName.equals(((EntityResultSegment) mapping)
+ .getClassDescriptor()
+ .getEntity()
+ .getName())) {
+ // if entity is included into SELECT clause, all its attributes are processed earlier
+ isProcessingOmitted = true;
+ break;
+ }
+
+ }
+ }
+
+ if (!isProcessingOmitted) {
+ Collection<ObjAttribute> attributes = context.getEntityDescriptor(
+ id.getEntityId()).getEntity().getAttributes();
+ for (ObjAttribute objAttribute : attributes) {
+ if (objAttribute.isFlattened()
+ && sourceExpression.contains(id.getEntityId()
+ + "."
+ + objAttribute.getName())) {
+ // joins for attribute are generated if it is flattened and appears in original statement
+ Iterator<CayenneMapEntry> dbPathIterator = objAttribute
+ .getDbPathIterator();
+ while (dbPathIterator.hasNext()) {
+ CayenneMapEntry next = dbPathIterator.next();
+ if (next instanceof DbRelationship) {
+ DbRelationship rel = (DbRelationship) next;
+ context.append(" JOIN ");
+ String targetEntityName = rel.getTargetEntityName();
+ String subqueryTargetAlias = context.getTableAlias(id
+ .getEntityId(), targetEntityName);
+ context.append(targetEntityName).append(' ').append(
+ subqueryTargetAlias);
+ generateJoiningExpression(rel, context.getTableAlias(id
+ .getEntityId(), rel.getSourceEntity().getName()), subqueryTargetAlias);
+ }
+
+ }
+ }
+
+ }
+ }
+ }
+
private EJBQLExpression ejbqlQualifierForEntityAndSubclasses(
Expression qualifier,
String entityId) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectColumnsTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectColumnsTranslator.java?rev=899270&r1=899269&r2=899270&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectColumnsTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectColumnsTranslator.java Thu Jan 14 16:21:02 2010
@@ -22,6 +22,7 @@
import java.util.Iterator;
import java.util.Map;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLException;
@@ -134,9 +135,45 @@
DbEntity table = currentEntity.getDbEntity();
String alias = this.lastAlias != null ? lastAlias : context
.getTableAlias(idPath, table.getFullyQualifiedName());
+ if (attribute.isFlattened()) {
+ Iterator<?> dbPathIterator = attribute.getDbPathIterator();
+ EJBQLTableId lhsId = new EJBQLTableId(idPath);
+
+ while (dbPathIterator.hasNext()) {
+ Object pathPart = dbPathIterator.next();
+ // DbRelationships not processed, because they will be processed
+ // later when appending table
+ if (pathPart == null) {
+ throw new CayenneRuntimeException(
+ "ObjAttribute has no component: "
+ + attribute.getName());
+ }
+ else if (pathPart instanceof DbAttribute) {
+ DbAttribute dbAttribute = (DbAttribute) pathPart;
+ appendColumn(
+ attribute,
+ context.getTableAlias(
+ lhsId.getEntityId(),
+ dbAttribute.getEntity().getName()),
+ dbAttribute);
- DbAttribute dbAttribute = attribute.getDbAttribute();
+ }
+ }
+
+ }
+ else {
+
+ DbAttribute dbAttribute = attribute.getDbAttribute();
+
+ appendColumn(attribute, alias, dbAttribute);
+ }
+ }
+
+ private void appendColumn(
+ ObjAttribute attribute,
+ String alias,
+ DbAttribute dbAttribute) {
if (context.isAppendingResultColumns()) {
context.append(" #result('");
}
@@ -163,6 +200,7 @@
.append(")");
}
}
+
};
expression.visit(pathTranslator);
return false;
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java?rev=899270&r1=899269&r2=899270&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java Thu Jan 14 16:21:02 2010
@@ -28,6 +28,7 @@
import org.apache.art.Artist;
import org.apache.art.CompoundPainting;
+import org.apache.art.Gallery;
import org.apache.cayenne.Cayenne;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.exp.ExpressionFactory;
@@ -203,11 +204,10 @@
public void testSelectEJQBQLCollectionTheta() throws Exception {
populateTables();
- EJBQLQuery query = new EJBQLQuery("SELECT a FROM CompoundPainting cp, Artist a "
+ EJBQLQuery query = new EJBQLQuery("SELECT DISTINCT a FROM CompoundPainting cp, Artist a "
+ "WHERE a.artistName=cp.artistName ORDER BY a.artistName");
- //TODO fails while the support for flattened attributes would not be added
- /*List<?> objects = context.performQuery(query);
+ List<?> objects = context.performQuery(query);
assertNotNull(objects);
assertEquals(4, objects.size());
@@ -217,7 +217,7 @@
Artist artist = (Artist) i.next();
assertEquals("artist" + index, artist.getArtistName());
index++;
- }*/
+ }
}
public void testSelectEJQBQLLike() throws Exception {
@@ -265,41 +265,31 @@
"SELECT g FROM Gallery g WHERE " +
"(SELECT COUNT(cp) FROM CompoundPainting cp WHERE g.galleryName=cp.galleryName) = 4");
-
- // TODO fails while the support for flattened attributes would not be added
- /*List<?> objects = context.performQuery(query);
+ List<?> objects = context.performQuery(query);
assertNotNull(objects);
- assertEquals(2, objects.size());
- Iterator<?> i = objects.iterator();
- int index=1;
- while (i.hasNext()) {
- Gallery gallery = (Gallery) i.next();
- assertEquals("gallery" + index, gallery.getGalleryName());
- index++;
- }*/
+ assertEquals(1, objects.size());
+ Gallery gallery = (Gallery) objects.get(0);
+ assertEquals("gallery2", gallery.getGalleryName());
+
}
public void testSelectEJQBQLHaving() throws Exception {
populateTables();
EJBQLQuery query = new EJBQLQuery(
- "SELECT cp.artistName FROM CompoundPainting cp " +
- "GROUP BY cp.artistName " +
- "HAVING cp.artistName IN ('artist1')");
+ "SELECT cp.galleryName, COUNT(a) from Artist a, CompoundPainting cp "+
+ "WHERE cp.artistName = a.artistName "+
+ "GROUP BY cp.galleryName " +
+ "HAVING cp.galleryName LIKE 'gallery1'");
- // TODO fails while the support for flattened attributes would not be added
- /* List<?> objects = context.performQuery(query);
+ List<Object[]> objects = context.performQuery(query);
assertNotNull(objects);
- assertEquals(2, objects.size());
- Iterator<?> i = objects.iterator();
- int index=1;
- while (i.hasNext()) {
- CompoundPainting painting = (CompoundPainting) i.next();
- assertEquals("painting" + index, painting.getPaintingTitle());
- index++;
- }*/
+ assertEquals(1, objects.size());
+ Object[] galleryItem = objects.get(0);
+ assertEquals("gallery1", galleryItem[0]);
+ assertEquals(3L, galleryItem[1]);
}
public void testInsert() {