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 2009/10/08 10:51:27 UTC
svn commit: r823092 - in /cayenne/main/trunk: docs/doc/src/main/resources/
framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/
framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/
framework/...
Author: aadamchik
Date: Thu Oct 8 08:51:26 2009
New Revision: 823092
URL: http://svn.apache.org/viewvc?rev=823092&view=rev
Log:
CAY-1145 EJBQL: Implement support for relationship-ending paths in SELECT clause
patch by Olga Tkachova
Modified:
cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.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/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/EJBQLQueryTest.java
Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=823092&r1=823091&r2=823092&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Thu Oct 8 08:51:26 2009
@@ -17,6 +17,7 @@
CAY-132 Intelligent lazy fault detection
CAY-419 Collections aren't supported with in-memory filtering
CAY-1116 Add generated PK support to SQLite
+CAY-1145 EJBQL: Implement support for relationship-ending paths in SELECT clause
CAY-1220 A function to auto-map the DB relationships
CAY-1225 Controlling JDBC Driver setting "fetchSize" in a SelectQuery
CAY-1227 Modeler support for flattened attributes
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java?rev=823092&r1=823091&r2=823092&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java Thu Oct 8 08:51:26 2009
@@ -105,7 +105,7 @@
return true;
}
- private void resolveJoin(boolean inner) {
+ protected void resolveJoin(boolean inner) {
EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(
context);
@@ -209,7 +209,7 @@
}
}
- private void processTerminatingRelationship(ObjRelationship relationship) {
+ protected void processTerminatingRelationship(ObjRelationship relationship) {
if (relationship.isSourceIndependentFromTargetChange()) {
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=823092&r1=823091&r2=823092&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 Oct 8 08:51:26 2009
@@ -18,12 +18,20 @@
****************************************************************/
package org.apache.cayenne.access.jdbc;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLException;
import org.apache.cayenne.ejbql.EJBQLExpression;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
/**
* Translator of the EJBQL select clause.
@@ -66,6 +74,62 @@
}
@Override
+ protected void processTerminatingRelationship(ObjRelationship relationship) {
+
+ Map<String, String> xfields = null;
+ if (context.isAppendingResultColumns()) {
+ xfields = context.nextEntityResult().getFields();
+ }
+
+ final Map<String, String> fields = xfields;
+
+ Collection<DbAttribute> dbAttr = ((ObjEntity) relationship
+ .getTargetEntity()).getDbEntity().getAttributes();
+
+ DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
+ DbEntity table = (DbEntity) dbRelationship.getTargetEntity();
+
+ Iterator<DbAttribute> it = dbAttr.iterator();
+ if (dbAttr.size() > 0) {
+ this.resolveJoin(false);
+ }
+
+ String alias = this.lastAlias != null ? lastAlias : context
+ .getTableAlias(idPath, table.getFullyQualifiedName());
+
+ boolean first = true;
+ while (it.hasNext()) {
+
+ context.append(!first ? ", " : " ");
+
+ DbAttribute dbAttribute = it.next();
+
+ if (context.isAppendingResultColumns()) {
+ context.append(" #result('");
+ }
+ else {
+ context.append(' ');
+ }
+
+ context.append(alias).append('.').append(dbAttribute.getName());
+
+ if (context.isAppendingResultColumns()) {
+
+ String javaType = TypesMapping.getJavaBySqlType(dbAttribute
+ .getType());
+ String columnLabel = fields.get(dbAttribute.getName());
+
+ context.append("' '").append(javaType).append("' '").append(
+ columnLabel).append("' '").append(columnLabel).append(
+ "' " + dbAttribute.getType()).append(")");
+ }
+
+ first = false;
+ }
+
+ }
+
+ @Override
protected void processTerminatingAttribute(ObjAttribute attribute) {
DbEntity table = currentEntity.getDbEntity();
String alias = this.lastAlias != null ? lastAlias : context
@@ -100,7 +164,6 @@
}
}
};
-
expression.visit(pathTranslator);
return false;
}
@@ -111,4 +174,5 @@
context));
return false;
}
+
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java?rev=823092&r1=823091&r2=823092&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java Thu Oct 8 08:51:26 2009
@@ -84,11 +84,57 @@
CompiledExpression compile(String source, EJBQLExpression parsed) {
parsed.visit(new CompilationVisitor());
+ Map<EJBQLPath, Integer> pathsInSelect = new HashMap<EJBQLPath, Integer>();
+
+ if (parsed != null) {
+ for (int i = 0; i < parsed.getChildrenCount(); i++) {
+ if (parsed.getChild(i) instanceof EJBQLSelectClause) {
+
+ EJBQLExpression parsedTemp = parsed.getChild(i);
+ boolean stop = false;
+
+ while (parsedTemp.getChildrenCount() > 0 && !stop) {
+ EJBQLExpression newParsedTemp = null;
+ for (int j = 0; j < parsedTemp.getChildrenCount(); j++) {
+ if (parsedTemp.getChild(j) instanceof EJBQLSelectExpression) {
+ for (int k = 0; k < parsedTemp
+ .getChild(j)
+ .getChildrenCount(); k++) {
+
+ if (parsedTemp.getChild(j).getChild(k) instanceof EJBQLPath) {
+ pathsInSelect.put((EJBQLPath) parsedTemp
+ .getChild(j)
+ .getChild(k), j);
+
+ }
+ }
+ }
+ else {
+ if (parsedTemp.getChild(j).getChildrenCount() == 0) {
+ stop = true;
+ }
+ else {
+ newParsedTemp = parsedTemp.getChild(j);
+ }
+ }
+ }
+
+ if (!stop && newParsedTemp != null) {
+ parsedTemp = newParsedTemp;
+ }
+ else {
+ stop = true;
+ }
+ }
+ }
+ }
+ }
+
// postprocess paths, now that all id vars are resolved
if (paths != null) {
+ int elenent = 0;
for (EJBQLPath path : paths) {
String id = normalizeIdPath(path.getId());
-
ClassDescriptor descriptor = descriptorsById.get(id);
if (descriptor == null) {
throw new EJBQLException("Unmapped id variable: " + id);
@@ -96,22 +142,41 @@
StringBuilder buffer = new StringBuilder(id);
+ ObjRelationship incoming = null;
+ String pathRelationshipString = "";
+
for (int i = 1; i < path.getChildrenCount(); i++) {
String pathChunk = path.getChild(i).getText();
buffer.append('.').append(pathChunk);
Property property = descriptor.getProperty(pathChunk);
+
if (property instanceof ArcProperty) {
- ObjRelationship incoming = ((ArcProperty) property)
- .getRelationship();
+ incoming = ((ArcProperty) property).getRelationship();
descriptor = ((ArcProperty) property).getTargetDescriptor();
- String pathString = buffer.substring(0, buffer.length());
+ pathRelationshipString = buffer.substring(0, buffer.length());
- descriptorsById.put(pathString, descriptor);
- incomingById.put(pathString, incoming);
+ descriptorsById.put(pathRelationshipString, descriptor);
+ incomingById.put(pathRelationshipString, incoming);
+
}
}
+
+
+ if (pathsInSelect.size() > 0
+ && incoming != null
+ && pathRelationshipString.length() > 0
+ && pathRelationshipString.equals(buffer.toString())) {
+
+ EJBQLIdentifier ident = new EJBQLIdentifier(0);
+ ident.text = pathRelationshipString;
+
+ resultComponents.remove(pathsInSelect.get(path).intValue());
+ resultComponents.add(pathsInSelect.get(path).intValue(), ident);
+ rootId = pathRelationshipString;
+ };
+ elenent++;
}
}
@@ -139,6 +204,7 @@
}
compiled.setResult(mapping);
+
}
return compiled;
@@ -147,6 +213,9 @@
private EntityResult compileEntityResult(EJBQLExpression expression, int position) {
String id = expression.getText().toLowerCase();
ClassDescriptor descriptor = descriptorsById.get(id);
+ if (descriptor == null) {
+ descriptor = descriptorsById.get(expression.getText());
+ }
final EntityResult entityResult = new EntityResult(descriptor.getObjectClass());
final String prefix = "ec" + position + "_";
final int[] index = {
@@ -197,7 +266,8 @@
}
// append inheritance discriminator columns...
- Iterator<ObjAttribute> discriminatorColumns = descriptor.getDiscriminatorColumns();
+ Iterator<ObjAttribute> discriminatorColumns = descriptor
+ .getDiscriminatorColumns();
while (discriminatorColumns.hasNext()) {
ObjAttribute column = discriminatorColumns.next();
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/EJBQLQueryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/EJBQLQueryTest.java?rev=823092&r1=823091&r2=823092&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/EJBQLQueryTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/EJBQLQueryTest.java Thu Oct 8 08:51:26 2009
@@ -24,6 +24,7 @@
import java.util.Map;
import org.apache.art.Artist;
+import org.apache.art.Painting;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
@@ -69,7 +70,7 @@
public void testCacheStrategy() throws Exception {
deleteTestData();
-
+
insertValue();
DataContext contex = createDataContext();
String ejbql = "select a FROM Artist a";
@@ -92,7 +93,7 @@
public void testDataRows() throws Exception {
deleteTestData();
-
+
insertValue();
String ejbql = "select a FROM Artist a";
EJBQLQuery query = new EJBQLQuery(ejbql);
@@ -101,7 +102,7 @@
Map row = (Map) artists.get(0);
String artistName = (String) row.get("ARTIST_NAME");
-
+
assertTrue(row instanceof DataRow);
Artist artist = (Artist) createDataContext().objectFromDataRow(
@@ -121,6 +122,19 @@
}
}
+ private void insertPaintValue() {
+ DataContext context = createDataContext();
+
+ for (int i = 0; i < 2; i++) {
+ Artist art = context.newObject(Artist.class);
+ art.setArtistName("a" + i);
+ Painting obj = context.newObject(Painting.class);
+ obj.setToArtist(art);
+ obj.setPaintingTitle("title" + i);
+ context.commitChanges();
+ }
+ }
+
public void testGetExpression() {
String ejbql = "select a FROM Artist a";
EJBQLQuery query = new EJBQLQuery(ejbql);
@@ -175,37 +189,78 @@
assertTrue(md.isResolvingInherited());
assertEquals(QueryCacheStrategy.NO_CACHE, md.getCacheStrategy());
}
-
- public void testEncodeAsXML() {
+
+ public void testSelectRelationship() {
+
+ insertPaintValue();
+ DataContext contex = createDataContext();
+ String ejbql = "SELECT p.toArtist FROM Painting p";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List result = contex.performQuery(query);
+
+ assertNotNull(result);
+ assertEquals(2, result.size());
+
+ assertEquals(Artist.class, result.get(0).getClass());
+
+
+ String ejbql2 = "SELECT p.toArtist, p FROM Painting p";
+ EJBQLQuery query2 = new EJBQLQuery(ejbql2);
+
+ List result2 = contex.performQuery(query2);
+
+ assertNotNull(result2);
+ assertEquals(2, result2.size());
+ assertEquals(2, ((Object[])result2.get(0)).length);
+
+ assertEquals(Artist.class,((Object[])result2.get(0))[0].getClass());
+ assertEquals(Painting.class,((Object[])result2.get(0))[1].getClass());
+
+ String ejbql3 = "SELECT p.toArtist, p.paintingTitle FROM Painting p";
+ EJBQLQuery query3 = new EJBQLQuery(ejbql3);
+
+ List result3 = contex.performQuery(query3);
+
+ assertNotNull(result3);
+ assertEquals(2, result3.size());
+ assertEquals(2, ((Object[])result3.get(0)).length);
+
+ assertEquals(Artist.class,((Object[])result3.get(0))[0].getClass());
+ assertEquals(String.class,((Object[])result3.get(0))[1].getClass());
+ }
+
+ public void testEncodeAsXML() {
+
String ejbql = "select a FROM Artist a";
String name = "Test";
-
+
StringWriter w = new StringWriter();
XMLEncoder e = new XMLEncoder(new PrintWriter(w));
-
+
String separator = System.getProperty("line.separator");
-
+
StringBuffer s = new StringBuffer("<query name=\"");
s.append(name);
s.append("\" factory=\"");
s.append("org.apache.cayenne.map.EjbqlBuilder");
s.append("\">");
s.append(separator);
-
+
EJBQLQuery query = new EJBQLQuery(ejbql);
-
+
if (query.getEjbqlStatement() != null) {
s.append("<ejbql><![CDATA[");
s.append(query.getEjbqlStatement());
s.append("]]></ejbql>");
}
s.append(separator);
- s.append("</query>");
+ s.append("</query>");
s.append(separator);
query.setName(name);
query.encodeAsXML(e);
-
+
assertEquals(w.getBuffer().toString(), s.toString());
}
}