You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by br...@apache.org on 2004/04/24 10:25:38 UTC
cvs commit: db-ojb/src/test/org/apache/ojb/broker PathTest.java AllTests.java
brj 2004/04/24 01:25:38
Modified: src/schema ojbtest-schema.xml
src/java/org/apache/ojb/broker/query BetweenCriteria.java
Criteria.java SelectionCriteria.java
src/java/org/apache/ojb/broker/accesslayer/sql
SqlQueryStatement.java SqlSelectStatement.java
src/test/org/apache/ojb repository.xml
src/test/org/apache/ojb/broker AllTests.java
Added: src/test/org/apache/ojb repository_junit_pathClass.xml
src/test/org/apache/ojb/broker PathTest.java
Log:
support pathClass-hints per Criteria (patch by Phil Warrick)
Revision Changes Path
1.75 +35 -1 db-ojb/src/schema/ojbtest-schema.xml
Index: ojbtest-schema.xml
===================================================================
RCS file: /home/cvs/db-ojb/src/schema/ojbtest-schema.xml,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -r1.74 -r1.75
--- ojbtest-schema.xml 19 Apr 2004 16:23:26 -0000 1.74
+++ ojbtest-schema.xml 24 Apr 2004 08:25:37 -0000 1.75
@@ -1314,4 +1314,38 @@
javaName="personId" />
</table>
-</database>
+ <!-- ************************************************* -->
+ <!-- Classes for path tests -->
+ <!-- ************************************************* -->
+
+ <table name="P_A_TABLE">
+ <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
+ <column name="A_ATTRIB" type="INTEGER" required="false"/>
+ </table>
+
+ <table name="P_B_TABLE">
+ <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
+ <column name="B_ATTRIB" type="INTEGER" required="false"/>
+ <column name="A_ID" type="BIGINT" required="true"/>
+ <foreign-key foreignTable="P_A_TABLE">
+ <reference local="A_ID" foreign="ID"/>
+ </foreign-key>
+ </table>
+
+ <table name="P_C_TABLE">
+ <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
+ <column name="C_ATTRIB" type="INTEGER" required="false"/>
+ <column name="C1_ATTRIB" type="INTEGER" required="false"/>
+ <column name="B_ID" type="BIGINT" required="true"/>
+ <column name="D_ID" type="BIGINT" required="false"/>
+ <foreign-key foreignTable="P_B_TABLE">
+ <reference local="B_ID" foreign="ID"/>
+ </foreign-key>
+ </table>
+
+ <table name="P_D_TABLE">
+ <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
+ <column name="D_ATTRIB" type="INTEGER" required="false"/>
+ </table>
+
+</database>
\ No newline at end of file
1.9 +8 -0 db-ojb/src/java/org/apache/ojb/broker/query/BetweenCriteria.java
Index: BetweenCriteria.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/BetweenCriteria.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- BetweenCriteria.java 4 Apr 2004 23:53:36 -0000 1.8
+++ BetweenCriteria.java 24 Apr 2004 08:25:37 -0000 1.9
@@ -77,5 +77,13 @@
return (getValue() == null && getValue2() == null);
}
+ // PAW
+ /**
+ * String representation
+ */
+ public String toString()
+ {
+ return super.toString() + " AND " + value2;
+ }
}
1.44 +102 -1 db-ojb/src/java/org/apache/ojb/broker/query/Criteria.java
Index: Criteria.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/Criteria.java,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- Criteria.java 21 Apr 2004 17:11:12 -0000 1.43
+++ Criteria.java 24 Apr 2004 08:25:37 -0000 1.44
@@ -18,8 +18,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Vector;
import org.apache.ojb.broker.PersistenceBrokerFactory;
@@ -76,6 +78,10 @@
private QueryByCriteria m_query;
private Criteria m_parentCriteria;
+ // PAW
+ // hint classes for paths of this criteria
+ private Map m_pathClasses;
+
/**
* Constructor declaration
*/
@@ -87,6 +93,8 @@
prefetchedRelationships = new ArrayList();
m_type = NONE;
m_embraced = false;
+ // PAW
+ m_pathClasses = new HashMap();
}
/**
@@ -1065,5 +1073,98 @@
{
m_negative = negative;
}
+
+ // PAW
+ /**
+ * Add a hint Class for a path. Used for relationships to extents.<br>
+ * SqlStatment will use these hint classes when resolving the path.
+ * Without these hints SqlStatment will use the base class the
+ * relationship points to ie: Article instead of CdArticle.
+ *
+ * @param aPath the path segment ie: allArticlesInGroup
+ * @param aClass the Class ie: CdArticle
+ * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
+ */
+ public void addPathClass(String aPath, Class aClass)
+ {
+ Object pathClasses = m_pathClasses.get(aPath);
+ if(pathClasses == null)
+ {
+ setPathClass(aPath,aClass);
+ }
+ else
+ {
+ List hints = (List)pathClasses;
+ hints.add(aClass);
+ m_pathClasses.put(aPath, hints);
+ }
+ }
+
+ /**
+ * Set the Class for a path. Used for relationships to extents.<br>
+ * SqlStatment will use this class when resolving the path.
+ * Without this hint SqlStatment will use the base class the
+ * relationship points to ie: Article instead of CdArticle.
+ * Using this method is the same as adding just one hint
+ *
+ * @param aPath the path segment ie: allArticlesInGroup
+ * @param aClass the Class ie: CdArticle
+ * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
+ * @see #addPathClass
+ */
+ public void setPathClass(String aPath, Class aClass)
+ {
+ List pathClasses = new ArrayList(1);
+ pathClasses.add(aClass);
+ m_pathClasses.put(aPath, pathClasses);
+ }
+
+ /**
+ * Get the a List of Class objects used as hints for a path
+ *
+ * @param aPath the path segment ie: allArticlesInGroup
+ * @return a List o Class objects to be used in SqlStatment
+ * @see #addPathClass
+ * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
+ */
+ public List getClassesForPath(String aPath)
+ {
+ return (List)getPathClasses().get(aPath);
+ }
+
+ /**
+ * Gets the pathClasses.
+ * A Map containing hints about what Class to be used for what path segment
+ * If local instance not set, try parent Criteria's instance. If this is
+ * the top-level Criteria, try the m_query's instance
+ * @return Returns a Map
+ */
+ public Map getPathClasses()
+ {
+ if (m_pathClasses.isEmpty())
+ {
+ if (m_parentCriteria == null)
+ {
+ if (m_query == null)
+ {
+ return m_pathClasses;
+ }
+ else
+ {
+ return m_query.getPathClasses();
+ }
+ }
+ else
+ {
+ return m_parentCriteria.getPathClasses();
+ }
+ }
+ else
+ {
+ return m_pathClasses;
+ }
+ }
+
+
}
1.16 +28 -0 db-ojb/src/java/org/apache/ojb/broker/query/SelectionCriteria.java
Index: SelectionCriteria.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/SelectionCriteria.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- SelectionCriteria.java 4 Apr 2004 23:53:36 -0000 1.15
+++ SelectionCriteria.java 24 Apr 2004 08:25:37 -0000 1.16
@@ -1,5 +1,8 @@
package org.apache.ojb.broker.query;
+import java.util.List;
+import java.util.Map;
+
/* Copyright 2002-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -234,5 +237,30 @@
return null;
}
}
+
+ /**
+ * Gets the pathClasses from the parent Criteria.
+ * A Map containing hints about what Class to be used for what path segment
+ * @return Returns a Map
+ */
+ // PAW
+ public Map getPathClasses()
+ {
+ return getCriteria().getPathClasses();
+ }
+
+ /**
+ * Get the a List of Class objects used as hints for a path
+ *
+ * @param aPath the path segment ie: allArticlesInGroup
+ * @return a List o Class objects to be used in SqlStatment
+ * @see #addPathClass
+ * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
+ */
+ public List getClassesForPath(String aPath)
+ {
+ return getCriteria().getClassesForPath(aPath);
+ }
+
}
1.72 +292 -285 db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
Index: SqlQueryStatement.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- SqlQueryStatement.java 4 Apr 2004 23:53:32 -0000 1.71
+++ SqlQueryStatement.java 24 Apr 2004 08:25:37 -0000 1.72
@@ -114,7 +114,7 @@
}
else
{
- m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null);
+ m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null, m_query.getPathClasses());
}
// Walk the super reference-descriptor
@@ -139,71 +139,72 @@
return m_searchCld;
}
- /**
- * Return the TableAlias and the PathInfo for an Attribute name<br>
- * field names in functions (ie: sum(name) ) are tried to resolve ie: name
- * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
- * also resolve pathExpression adress.city or owner.konti.saldo
- * @param attr
- * @param useOuterJoins
- * @param aUserAlias
- * @return ColumnInfo
- */
- protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, String aUserAlias)
- {
- AttributeInfo result = new AttributeInfo();
- TableAlias tableAlias = null;
- SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
- String colName = pathInfo.column;
- int sp;
-
- // BRJ:
- // check if we refer to an attribute in the parent query
- // this prefix is temporary !
- if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
- {
- String[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
- return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias);
- }
-
- sp = colName.lastIndexOf(".");
- if (sp == -1)
- {
- tableAlias = getRoot();
- }
- else
- {
- String pathName = colName.substring(0, sp);
- String[] fieldNameRef = {colName.substring(sp + 1)};
-
- tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef);
- /**
- * if we have not found an alias by the pathName or
- * aliasName (if given), try again because pathName
- * may be an aliasname. it can be only and only if it is not
- * a path, which means there may be no path separators (,)
- * in the pathName.
- */
- if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
- {
- /**
- * pathName might be an alias, so check this first
- */
- tableAlias = getTableAlias(null, useOuterJoins, pathName, null);
- }
-
- if (tableAlias != null)
- {
- // correct column name to match the alias
- // productGroup.groupName -> groupName
- pathInfo.column = fieldNameRef[0];
- }
- }
-
- result.tableAlias = tableAlias;
- result.pathInfo = pathInfo;
- return result;
- }
+ /**
+ * Return the TableAlias and the PathInfo for an Attribute name<br>
+ * field names in functions (ie: sum(name) ) are tried to resolve ie: name
+ * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
+ * also resolve pathExpression adress.city or owner.konti.saldo
+ * @param attr
+ * @param useOuterJoins
+ * @param aUserAlias
+ * @param pathClasses
+ * @return ColumnInfo
+ */
+ protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, String aUserAlias, Map pathClasses)
+ {
+ AttributeInfo result = new AttributeInfo();
+ TableAlias tableAlias = null;
+ SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
+ String colName = pathInfo.column;
+ int sp;
+
+ // BRJ:
+ // check if we refer to an attribute in the parent query
+ // this prefix is temporary !
+ if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
+ {
+ String[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
+ return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias, pathClasses);
+ }
+
+ sp = colName.lastIndexOf(".");
+ if (sp == -1)
+ {
+ tableAlias = getRoot();
+ }
+ else
+ {
+ String pathName = colName.substring(0, sp);
+ String[] fieldNameRef = {colName.substring(sp + 1)};
+
+ tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
+ /**
+ * if we have not found an alias by the pathName or
+ * aliasName (if given), try again because pathName
+ * may be an aliasname. it can be only and only if it is not
+ * a path, which means there may be no path separators (,)
+ * in the pathName.
+ */
+ if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
+ {
+ /**
+ * pathName might be an alias, so check this first
+ */
+ tableAlias = getTableAlias(null, useOuterJoins, pathName, null, pathClasses);
+ }
+
+ if (tableAlias != null)
+ {
+ // correct column name to match the alias
+ // productGroup.groupName -> groupName
+ pathInfo.column = fieldNameRef[0];
+ }
+ }
+
+ result.tableAlias = tableAlias;
+ result.pathInfo = pathInfo;
+ return result;
+ }
/**
* Answer the column name for alias and path info<br>
@@ -420,7 +421,8 @@
*/
protected boolean appendColName(String attr, boolean useOuterJoins, String aUserAlias, StringBuffer buf)
{
- AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias);
+ // PAW: is this correct for pathClasses ?
+ AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
TableAlias tableAlias = attrInfo.tableAlias;
return appendColName(tableAlias, attrInfo.pathInfo, true, buf);
@@ -444,7 +446,8 @@
protected boolean appendColName(String attr, String attrAlias, boolean useOuterJoins, String aUserAlias,
StringBuffer buf)
{
- AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias);
+ // PAW: is this correct for pathClasses ?
+ AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
TableAlias tableAlias = attrInfo.tableAlias;
PathInfo pi = attrInfo.pathInfo;
@@ -822,7 +825,7 @@
return;
}
- AttributeInfo attrInfo = getAttributeInfo((String) c.getAttribute(), false, c.getAlias());
+ AttributeInfo attrInfo = getAttributeInfo((String) c.getAttribute(), false, c.getAlias(), c.getPathClasses());
TableAlias alias = attrInfo.tableAlias;
if (alias != null)
@@ -908,156 +911,157 @@
return sql;
}
- /**
- * Get TableAlias by the path from the target table of the query.
- * @param aPath the path from the target table of the query to this TableAlias.
- * @param useOuterJoins use outer join to join this table with the previous
- * table in the path.
- * @param aUserAlias
- * @param fieldRef String[1] contains the field name.
- * In the case of related table's primary key the "related.pk" attribute
- * must not add new join, but use the value of foreign key
- */
- private TableAlias getTableAlias(String aPath, boolean useOuterJoins, String aUserAlias, String[] fieldRef)
- {
- TableAlias curr, prev, indirect;
- String attr, attrPath = null;
- ObjectReferenceDescriptor ord;
- CollectionDescriptor cod;
- ClassDescriptor cld = null;
- Object[] prevKeys = null;
- Object[] keys = null;
- ArrayList descriptors;
- boolean outer = useOuterJoins;
- int pathLength;
-
- curr = getTableAliasForPath(aPath, aUserAlias);
-
- if (curr != null)
- {
- return curr;
- }
-
- descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, getQuery().getPathClasses());
- prev = getRoot();
-
- if (descriptors == null || descriptors.size() == 0)
- {
- if (prev.hasJoins())
- {
- for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
- {
- prev = ((Join) itr.next()).left;
- descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, getQuery().getPathClasses());
- if (descriptors.size() > 0)
- {
- break;
- }
- }
- }
- }
-
- pathLength = descriptors.size();
- for (int i = 0; i < pathLength; i++)
- {
- if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
- {
- // only use Collection- and ObjectReferenceDescriptor
- continue;
- }
-
- ord = (ObjectReferenceDescriptor) descriptors.get(i);
- attr = ord.getAttributeName();
- if (attrPath == null)
- {
- attrPath = attr;
- }
- else
- {
- attrPath = attrPath + "." + attr;
- }
-
- // look for outer join hint
- outer = outer || getQuery().isPathOuterJoin(attr);
-
- // look for 1:n or m:n
- if (ord instanceof CollectionDescriptor)
- {
- cod = (CollectionDescriptor) ord;
- cld = getItemClassDescriptor(cod, attrPath);
-
- if (!cod.isMtoNRelation())
- {
- prevKeys = prev.cld.getPkFields();
- keys = cod.getForeignKeyFieldDescriptors(cld);
- }
- else
- {
- String mnAttrPath = attrPath + "*";
- String mnPath = aPath + "*";
- String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
- indirect = getTableAliasForPath(mnAttrPath, mnUserAlias, mnPath);
- if (indirect == null)
- {
- indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias, mnPath);
-
- // we need two Joins for m:n
- // 1.) prev class to indirectionTable
- prevKeys = prev.cld.getPkFields();
- keys = cod.getFksToThisClass();
- addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
- }
- // 2.) indirectionTable to the current Class
- prev = indirect;
- prevKeys = cod.getFksToItemClass();
- keys = cld.getPkFields();
- }
- }
- else
- {
- // must be n:1 or 1:1
- cld = getItemClassDescriptor(ord, attrPath);
-
- prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
- keys = cld.getPkFields();
-
- // [olegnitz]
- // a special case: the last element of the path is
- // reference and the field is one of PK fields =>
- // use the correspondent foreign key field, don't add the join
- if ((fieldRef != null) && (i == (pathLength - 1)))
- {
- FieldDescriptor[] pk = cld.getPkFields();
-
- for (int j = 0; j < pk.length; j++)
- {
- if (pk[j].getAttributeName().equals(fieldRef[0]))
- {
- fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
- return prev;
- }
- }
- }
- }
+ /**
+ * Get TableAlias by the path from the target table of the query.
+ * @param aPath the path from the target table of the query to this TableAlias.
+ * @param useOuterJoins use outer join to join this table with the previous
+ * table in the path.
+ * @param aUserAlias if specified, overrides alias in crit
+ * @param fieldRef String[1] contains the field name.
+ * In the case of related table's primary key the "related.pk" attribute
+ * must not add new join, but use the value of foreign key
+ * @param pathClasses the hints
+ */
+ private TableAlias getTableAlias(String aPath, boolean useOuterJoins, String aUserAlias, String[] fieldRef, Map pathClasses)
+ {
+ TableAlias curr, prev, indirect;
+ String attr, attrPath = null;
+ ObjectReferenceDescriptor ord;
+ CollectionDescriptor cod;
+ ClassDescriptor cld = null;
+ Object[] prevKeys = null;
+ Object[] keys = null;
+ ArrayList descriptors;
+ boolean outer = useOuterJoins;
+ int pathLength;
+
+ curr = getTableAliasForPath(aPath, aUserAlias);
+
+ if (curr != null)
+ {
+ return curr;
+ }
+
+ descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, pathClasses);
+ prev = getRoot();
+
+ if (descriptors == null || descriptors.size() == 0)
+ {
+ if (prev.hasJoins())
+ {
+ for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
+ {
+ prev = ((Join) itr.next()).left;
+ descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, pathClasses);
+ if (descriptors.size() > 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ pathLength = descriptors.size();
+ for (int i = 0; i < pathLength; i++)
+ {
+ if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
+ {
+ // only use Collection- and ObjectReferenceDescriptor
+ continue;
+ }
+
+ ord = (ObjectReferenceDescriptor) descriptors.get(i);
+ attr = ord.getAttributeName();
+ if (attrPath == null)
+ {
+ attrPath = attr;
+ }
+ else
+ {
+ attrPath = attrPath + "." + attr;
+ }
+
+ // look for outer join hint
+ outer = outer || getQuery().isPathOuterJoin(attr);
+
+ // look for 1:n or m:n
+ if (ord instanceof CollectionDescriptor)
+ {
+ cod = (CollectionDescriptor) ord;
+ cld = getItemClassDescriptor(cod, attrPath, pathClasses);
+
+ if (!cod.isMtoNRelation())
+ {
+ prevKeys = prev.cld.getPkFields();
+ keys = cod.getForeignKeyFieldDescriptors(cld);
+ }
+ else
+ {
+ String mnAttrPath = attrPath + "*";
+ String mnPath = aPath + "*";
+ String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
+ indirect = getTableAliasForPath(mnAttrPath, mnUserAlias, mnPath);
+ if (indirect == null)
+ {
+ indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias, mnPath);
+
+ // we need two Joins for m:n
+ // 1.) prev class to indirectionTable
+ prevKeys = prev.cld.getPkFields();
+ keys = cod.getFksToThisClass();
+ addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
+ }
+ // 2.) indirectionTable to the current Class
+ prev = indirect;
+ prevKeys = cod.getFksToItemClass();
+ keys = cld.getPkFields();
+ }
+ }
+ else
+ {
+ // must be n:1 or 1:1
+ cld = getItemClassDescriptor(ord, attrPath, pathClasses);
+
+ prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
+ keys = cld.getPkFields();
+
+ // [olegnitz]
+ // a special case: the last element of the path is
+ // reference and the field is one of PK fields =>
+ // use the correspondent foreign key field, don't add the join
+ if ((fieldRef != null) && (i == (pathLength - 1)))
+ {
+ FieldDescriptor[] pk = cld.getPkFields();
+
+ for (int j = 0; j < pk.length; j++)
+ {
+ if (pk[j].getAttributeName().equals(fieldRef[0]))
+ {
+ fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
+ return prev;
+ }
+ }
+ }
+ }
+
+ curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
+
+ if (curr == null)
+ {
+ List hintClasses = (List) pathClasses.get(aPath);
+ curr = createTableAlias(cld, attrPath, aUserAlias, aPath, hintClasses);
+
+ outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
+ addJoin(prev, prevKeys, curr, keys, outer, attr);
- curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
+ buildSuperJoinTree(curr, cld, aPath);
+ }
- if (curr == null)
- {
- List hintClasses = (List) getQuery().getPathClasses().get(aPath);
- curr = createTableAlias(cld, attrPath, aUserAlias, aPath, hintClasses);
+ prev = curr;
+ }
- outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
- addJoin(prev, prevKeys, curr, keys, outer, attr);
-
- buildSuperJoinTree(curr, cld, aPath);
- }
-
- prev = curr;
- }
-
- return curr;
- }
+ return curr;
+ }
/**
* add a join between two aliases
@@ -1168,14 +1172,14 @@
private TableAlias createTableAlias(ClassDescriptor aCld, String aPath, String aUserAlias, String anOriginalPath,
List hints)
{
- if (aUserAlias == null || !anOriginalPath.equals(aPath))
- {
- return createTableAlias(aCld, hints, aPath);
- }
- else
- {
- return createTableAlias(aCld, hints, aUserAlias);
- }
+ if (aUserAlias == null)
+ {
+ return createTableAlias(aCld, hints, aPath);
+ }
+ else
+ {
+ return createTableAlias(aCld, hints, aUserAlias + aPath);
+ }
}
/**
@@ -1211,14 +1215,14 @@
*/
private TableAlias createTableAlias(String aTable, String aPath, String aUserAlias, String anOriginalPath)
{
- if (aUserAlias == null || !anOriginalPath.equals(aPath))
- {
- return createTableAlias(aTable, aPath);
- }
- else
- {
- return createTableAlias(aTable, aUserAlias);
- }
+ if (aUserAlias == null)
+ {
+ return createTableAlias(aTable, aPath);
+ }
+ else
+ {
+ return createTableAlias(aTable, aUserAlias + aPath);
+ }
}
/**
@@ -1266,7 +1270,7 @@
}
else
{
- return getTableAliasForPath(aUserAlias);
+ return getTableAliasForPath(aUserAlias + aPath);
}
}
@@ -1287,42 +1291,46 @@
}
else
{
- return getTableAliasForPath(aUserAlias);
+ return getTableAliasForPath(aUserAlias + aPath);
}
}
- /**
- * TODO: add super ClassDescriptor
- * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
- * check optional hint;
- */
- private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr)
- {
- List itemClasses = null;
- Query q = getQuery();
-
- if (q instanceof QueryByCriteria)
- {
- itemClasses = ((QueryByCriteria) q).getClassesForPath(attr);
- }
-
- if (itemClasses == null)
- {
- itemClasses = new ArrayList();
- itemClasses.add(ord.getItemClass());
- }
-
- List classDescriptors = new ArrayList(itemClasses.size());
- DescriptorRepository repo = ord.getClassDescriptor().getRepository();
-
- for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
- {
- Class clazz = (Class) iter.next();
- classDescriptors.add(repo.getDescriptorFor(clazz));
- }
- return (ClassDescriptor) classDescriptors.get(0);
+ /**
+ * TODO: add super ClassDescriptor
+ * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
+ * check optional hint;
+ */
+ private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr, Map pathClasses)
+ {
+ /* PAW
+ List itemClasses = null;
+ Query q = getQuery();
+
+ if (q instanceof QueryByCriteria)
+ {
+ itemClasses = ((QueryByCriteria) q).getClassesForPath(attr);
+ }
+ */
+
+ List itemClasses = (List)pathClasses.get(attr);
+
+ if (itemClasses == null)
+ {
+ itemClasses = new ArrayList();
+ itemClasses.add(ord.getItemClass());
+ }
+
+ List classDescriptors = new ArrayList(itemClasses.size());
+ DescriptorRepository repo = ord.getClassDescriptor().getRepository();
+
+ for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
+ {
+ Class clazz = (Class) iter.next();
+ classDescriptors.add(repo.getDescriptorFor(clazz));
+ }
- }
+ return (ClassDescriptor) classDescriptors.get(0);
+ }
/**
* Appends to the statement the ORDER BY clause for the Query
@@ -1552,34 +1560,33 @@
// BRJ: do not build join tree for subQuery attribute
if (c.getAttribute() != null && c.getAttribute() instanceof String)
{
- buildJoinTreeForColumn((String) c.getAttribute(), useOuterJoin, c.getAlias());
+ buildJoinTreeForColumn((String) c.getAttribute(), useOuterJoin, c.getAlias(), c.getPathClasses());
}
if (c instanceof FieldCriteria)
{
FieldCriteria cc = (FieldCriteria) c;
- buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, c.getAlias());
+ buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, c.getAlias(), c.getPathClasses());
}
}
}
}
- /**
- * build the Join-Information for name
- * functions and the last segment are removed
- * ie: avg(accounts.amount) -> accounts
- */
- private void buildJoinTreeForColumn(String aColName, boolean useOuterJoin, String aUserAlias)
- {
- String pathName = SqlHelper.cleanPath(aColName);
- int sepPos = pathName.lastIndexOf(".");
-
- if (sepPos >= 0)
- {
- getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias, new String[]{pathName
- .substring(sepPos + 1)});
- }
-
- }
+ /**
+ * build the Join-Information for name
+ * functions and the last segment are removed
+ * ie: avg(accounts.amount) -> accounts
+ */
+ private void buildJoinTreeForColumn(String aColName, boolean useOuterJoin, String aUserAlias, Map pathClasses)
+ {
+ String pathName = SqlHelper.cleanPath(aColName);
+ int sepPos = pathName.lastIndexOf(".");
+
+ if (sepPos >= 0)
+ {
+ getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias,
+ new String[]{pathName.substring(sepPos + 1)}, pathClasses);
+ }
+ }
/**
* build the Join-Information if a super reference exists
1.22 +4 -2 db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
Index: SqlSelectStatement.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- SqlSelectStatement.java 4 Apr 2004 23:53:32 -0000 1.21
+++ SqlSelectStatement.java 24 Apr 2004 08:25:38 -0000 1.22
@@ -209,7 +209,9 @@
{
for (int i = 0; i < joinAttributes.length; i++)
{
- getAttributeInfo(joinAttributes[i], false, null);
+ // PAW: correct for pathClasses?
+ //getAttributeInfo(joinAttributes[i], false, null);
+ getAttributeInfo(joinAttributes[i], false, null, getQuery().getPathClasses());
}
}
1.23 +2 -0 db-ojb/src/test/org/apache/ojb/repository.xml
Index: repository.xml
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository.xml,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- repository.xml 5 Apr 2004 13:58:59 -0000 1.22
+++ repository.xml 24 Apr 2004 08:25:38 -0000 1.23
@@ -47,6 +47,7 @@
<!ENTITY junit_meta_seq SYSTEM "repository_junit_meta_seq.xml">
<!ENTITY junit_model SYSTEM "repository_junit_model.xml">
<!ENTITY junit_cloneable SYSTEM "repository_junit_cloneable.xml">
+<!ENTITY junit_pathClass SYSTEM "repository_junit_pathClass.xml">
<!ENTITY user SYSTEM "repository_user.xml">
<!ENTITY ejb SYSTEM "repository_ejb.xml">
@@ -77,6 +78,7 @@
&junit_meta_seq;
&junit_model;
&junit_cloneable;
+ &junit_pathClass;
1.1 db-ojb/src/test/org/apache/ojb/repository_junit_pathClass.xml
Index: repository_junit_pathClass.xml
===================================================================
<!-- ojb test pathClass classes -->
<class-descriptor class="org.apache.ojb.broker.PathTest$A" table="P_A_TABLE">
<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
<field-descriptor name="aAttrib" column="A_ATTRIB" jdbc-type="INTEGER"/>
<collection-descriptor
name="bSet"
element-class-ref="org.apache.ojb.broker.PathTest$B"
auto-retrieve="true"
auto-update="false"
>
<inverse-foreignkey field-ref="aId"/>
</collection-descriptor>
</class-descriptor>
<class-descriptor class="org.apache.ojb.broker.PathTest$B" table="P_B_TABLE">
<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
<field-descriptor name="bAttrib" column="B_ATTRIB" jdbc-type="INTEGER"/>
<field-descriptor name="aId" column="A_ID" jdbc-type="BIGINT"/>
<reference-descriptor name="a" class-ref="org.apache.ojb.broker.PathTest$A"><foreignkey field-ref="aId"/></reference-descriptor>
<collection-descriptor
name="cSet"
element-class-ref="org.apache.ojb.broker.PathTest$C"
auto-retrieve="true"
auto-update="false"
>
<inverse-foreignkey field-ref="bId"/>
</collection-descriptor>
</class-descriptor>
<class-descriptor class="org.apache.ojb.broker.PathTest$C" table="P_C_TABLE">
<extent-class class-ref="org.apache.ojb.broker.PathTest$C1" />
<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
<field-descriptor name="cAttrib" column="C_ATTRIB" jdbc-type="INTEGER"/>
<field-descriptor name="bId" column="B_ID" jdbc-type="BIGINT"/>
<reference-descriptor name="b" class-ref="org.apache.ojb.broker.PathTest$B"><foreignkey field-ref="bId"/></reference-descriptor>
<field-descriptor name="dId" column="D_ID" jdbc-type="BIGINT"/>
<reference-descriptor name="d" class-ref="org.apache.ojb.broker.PathTest$D"><foreignkey field-ref="dId"/></reference-descriptor>
</class-descriptor>
<class-descriptor class="org.apache.ojb.broker.PathTest$C1" table="P_C_TABLE">
<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
<field-descriptor name="cAttrib" column="C_ATTRIB" jdbc-type="INTEGER"/>
<field-descriptor name="c1Attrib" column="C1_ATTRIB" jdbc-type="INTEGER"/>
<field-descriptor name="bId" column="B_ID" jdbc-type="BIGINT"/>
<reference-descriptor name="b" class-ref="org.apache.ojb.broker.PathTest$B"><foreignkey field-ref="bId"/></reference-descriptor>
<field-descriptor name="dId" column="D_ID" jdbc-type="BIGINT"/>
<reference-descriptor name="d" class-ref="org.apache.ojb.broker.PathTest$D"><foreignkey field-ref="dId"/></reference-descriptor>
</class-descriptor>
<class-descriptor class="org.apache.ojb.broker.PathTest$D" table="P_D_TABLE">
<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
<field-descriptor name="dAttrib" column="D_ATTRIB" jdbc-type="INTEGER"/>
</class-descriptor>
<!-- ojb test pathClass classes -->
1.45 +1 -0 db-ojb/src/test/org/apache/ojb/broker/AllTests.java
Index: AllTests.java
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/broker/AllTests.java,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- AllTests.java 19 Apr 2004 16:31:15 -0000 1.44
+++ AllTests.java 24 Apr 2004 08:25:38 -0000 1.45
@@ -91,6 +91,7 @@
suite.addTestSuite(CollectionTest2.class);
suite.addTestSuite(NumberAccuracyTest.class);
suite.addTestSuite(AutoIncrementTest.class);
+ suite.addTestSuite(PathTest.class);
return suite;
}
1.1 db-ojb/src/test/org/apache/ojb/broker/PathTest.java
Index: PathTest.java
===================================================================
package org.apache.ojb.broker;
/**
* TestClasses for Per-Criteria-Path-Hints
* @author PAW
*
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import junit.framework.TestCase;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.QueryFactory;
public class PathTest extends TestCase
{
private static Class CLASS = PathTest.class;
private int COUNT = 10;
private int id_filter = 10000;
private PersistenceBroker broker = null;
public static void main(String[] args)
{
String[] arr = {CLASS.getName()};
junit.textui.TestRunner.main(arr);
}
/**
* Insert the method's description here.
* Creation date: (06.12.2000 21:58:53)
*/
public void setUp()
{
try
{
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
}
catch (PBFactoryException e)
{
}
}
/**
* Insert the method's description here.
* Creation date: (06.12.2000 21:59:14)
*/
public void tearDown()
{
broker.close();
}
public PathTest(String name)
{
super(name);
}
public void testDeleteData() throws Exception
{
broker.beginTransaction();
Criteria crit = new Criteria();
Query query = QueryFactory.newQuery(D.class, crit);
Collection Ds = broker.getCollectionByQuery(query);
for (Iterator iterator = Ds.iterator(); iterator.hasNext();)
{
broker.delete(iterator.next());
}
query = QueryFactory.newQuery(C.class, crit);
Collection Cs = broker.getCollectionByQuery(query);
for (Iterator iterator = Cs.iterator(); iterator.hasNext();)
{
broker.delete(iterator.next());
}
query = QueryFactory.newQuery(B.class, crit);
Collection Bs = broker.getCollectionByQuery(query);
for (Iterator iterator = Bs.iterator(); iterator.hasNext();)
{
broker.delete(iterator.next());
}
query = QueryFactory.newQuery(A.class, crit);
Collection As = broker.getCollectionByQuery(query);
for (Iterator iterator = As.iterator(); iterator.hasNext();)
{
broker.delete(iterator.next());
}
broker.commitTransaction();
}
private static int NUM_A = 1;
private static int NUM_B_PER_A = 4;
private static int NUM_C_PER_B = 2;
private static int NUM_C1_PER_B = 3;
private static int NUM_D_PER_C = 1;
private static int A_OFFSET = 10000;
private static int B_OFFSET = 1000;
private static int C_OFFSET = 100;
private static int D_OFFSET = 10;
public void testCreateData() throws Exception
{
broker.beginTransaction();
A a = new A(A_OFFSET);
broker.store(a);
for (int i = 0; i < NUM_B_PER_A; i++)
{
B b = new B(A_OFFSET + B_OFFSET * i);
b.setA(a);
broker.store(b);
for (int j = 0; j < NUM_C_PER_B; j++)
{
C c = new C(A_OFFSET + B_OFFSET * i + C_OFFSET * j);
c.setB(b);
D d = new D(A_OFFSET + B_OFFSET * i + C_OFFSET * j + D_OFFSET);
c.setD(d);
broker.store(d);
broker.store(c);
}
for (int j = 0; j < NUM_C1_PER_B; j++)
{
C1 c1 = new C1(A_OFFSET + B_OFFSET * i + C_OFFSET * j);
c1.setB(b);
D d = new D(A_OFFSET + B_OFFSET * i + C_OFFSET * j + D_OFFSET);
c1.setD(d);
c1.setC1Attrib(c1.getCAttrib() + 1);
broker.store(d);
broker.store(c1);
}
}
broker.commitTransaction();
broker.clearCache();
Criteria crit = new Criteria();
Query query = QueryFactory.newQuery(A.class, crit);
Collection As = broker.getCollectionByQuery(query);
assertEquals(As.size(), NUM_A);
query = QueryFactory.newQuery(B.class, crit);
Collection Bs = broker.getCollectionByQuery(query);
int numB = NUM_A * NUM_B_PER_A;
assertEquals(Bs.size(), numB);
query = QueryFactory.newQuery(C.class, crit);
Collection Cs = broker.getCollectionByQuery(query);
int numC = numB * (NUM_C_PER_B + NUM_C1_PER_B);
assertEquals(Cs.size(), numC);
query = QueryFactory.newQuery(D.class, crit);
Collection Ds = broker.getCollectionByQuery(query);
int numD = numC * NUM_D_PER_C;
assertEquals(Ds.size(), numD);
}
public void testPathClassPerCriteria() throws Exception
{
try
{
// one EDBranch
Criteria crit1 = new Criteria();
crit1.setAlias("alias1");
crit1.addEqualTo("cSet.cAttrib", new Integer("10200"));
crit1.addPathClass("cSet", C.class);
// one EDLeaf
Criteria crit2 = new Criteria();
crit2.setAlias("alias2");
crit2.addEqualTo("cSet.c1Attrib", new Integer("10001"));
crit2.addPathClass("cSet", C1.class);
crit1.addAndCriteria(crit2);
Query query = new QueryByCriteria(B.class, crit1);
Collection allBs = broker.getCollectionByQuery(query);
java.util.Iterator itr = allBs.iterator();
assertEquals(allBs.size(), 1);
System.out.println("testPathClassPerCriteria() iteration size:" + allBs.size());
while (itr.hasNext())
{
B b = (B) itr.next();
System.out.println("Found B: " + b.getId() + " " + b.getBAttrib());
}
}
catch (Throwable t)
{
t.printStackTrace(System.out);
fail("testPathClassPerCriteria: " + t.getMessage());
}
}
// Inner Classes
public static class A
{
private long id;
private int aAttrib;
private Collection bSet;
public A()
{
}
public A(int aAttrib)
{
this.aAttrib = aAttrib;
this.bSet = new ArrayList();
}
/**
* @return
*/
public int getAAttrib()
{
return aAttrib;
}
/**
* @return
*/
public Collection getBSet()
{
return bSet;
}
/**
* @return
*/
public long getId()
{
return id;
}
/**
* @param i
*/
public void setAAttrib(int i)
{
aAttrib = i;
}
/**
* @param collection
*/
public void setBSet(Collection collection)
{
bSet = collection;
}
/**
* @param l
*/
public void setId(long l)
{
id = l;
}
}
public static class B
{
private long id;
private long aId;
private int bAttrib;
private A a;
private Collection cSet;
public B()
{
}
public B(int bAttrib)
{
this.bAttrib = bAttrib;
this.cSet = new ArrayList();
}
/**
* @return
*/
public int getBAttrib()
{
return bAttrib;
}
/**
* @return
*/
public Collection getCSet()
{
return cSet;
}
/**
* @return
*/
public long getId()
{
return id;
}
/**
* @param i
*/
public void setBAttrib(int i)
{
bAttrib = i;
}
/**
* @param collection
*/
public void setCSet(Collection collection)
{
cSet = collection;
}
/**
* @param l
*/
public void setId(long l)
{
id = l;
}
/**
* @return
*/
public A getA()
{
return a;
}
/**
* @param a
*/
public void setA(A a)
{
this.a = a;
a.getBSet().add(this);
}
}
public static class C
{
private long id;
private long bId;
private B b;
private long dId;
private D d;
private int cAttrib;
public C()
{
}
public C(int cAttrib)
{
this.cAttrib = cAttrib;
}
/**
* @return
*/
public int getCAttrib()
{
return cAttrib;
}
/**
* @return
*/
public D getD()
{
return d;
}
/**
* @return
*/
public long getId()
{
return id;
}
/**
* @param i
*/
public void setCAttrib(int i)
{
cAttrib = i;
}
/**
* @param collection
*/
public void setD(D d)
{
this.d = d;
}
/**
* @param l
*/
public void setId(long l)
{
id = l;
}
/**
* @return
*/
public B getB()
{
return b;
}
/**
* @param b
*/
public void setB(B b)
{
this.b = b;
b.getCSet().add(this);
}
}
public static class C1 extends C
{
private int c1Attrib;
/**
* @param cAttrib
*/
public C1()
{
}
public C1(int cAttrib)
{
super(cAttrib);
}
/**
* @return
*/
public int getC1Attrib()
{
return c1Attrib;
}
/**
* @param i
*/
public void setC1Attrib(int i)
{
c1Attrib = i;
}
}
public static class D
{
private long id;
private int dAttrib;
public D()
{
}
public D(int dAttrib)
{
this.dAttrib = dAttrib;
}
/**
* @return
*/
public int getDAttrib()
{
return dAttrib;
}
/**
* @return
*/
public long getId()
{
return id;
}
/**
* @param i
*/
public void setDAttrib(int i)
{
dAttrib = i;
}
/**
* @param l
*/
public void setId(long l)
{
id = l;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org