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 Phil Warrick <ph...@mcgill.ca> on 2004/03/27 22:33:12 UTC

Re: Per-criteria pathClass [was ojb-user: Query casts] 2 of 2

Hi,

I will have to learn to work with patches it seems. 
SqlQueryStatement.java was too long, so here is the patch.  Note that my 
changes were based on version 1.68 and we're up to 1.70 now as of a few 
minutes ago :)

Phil



Index: SqlQueryStatement.java
===================================================================
RCS file: 
/home/cvspublic/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v
retrieving revision 1.68
diff -u -r1.68 SqlQueryStatement.java
--- SqlQueryStatement.java	11 Mar 2004 18:16:08 -0000	1.68
+++ SqlQueryStatement.java	27 Mar 2004 21:25:10 -0000
@@ -114,7 +114,9 @@
          }
          else
          {
-            m_search = 
getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null);
+        	// PAW
+			//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 +141,147 @@
          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
+	 * @return ColumnInfo
+	 */
+	// PAW
+	// Todo: merge with other original getAttributeInfo(...)
+	//protected AttributeInfo getAttributeInfo(String attr, boolean 
useOuterJoins, String aUserAlias)
+	protected AttributeInfo getAttributeInfo(String attr, boolean 
useOuterJoins, String aUserAlias, Map pathClasses)
+	//protected AttributeInfo getAttributeInfo(SelectionCriteria crit, 
boolean useOuterJoins)
+	{
+		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())};
+			// PAW: is pathClasses the correct argument to pass to parent?
+			//return m_parentStatement.getAttributeInfo(fieldNameRef[0], 
useOuterJoins, aUserAlias, pathClasses);
+			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)};
+
+			// PAW
+			//tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, 
fieldNameRef);
+			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
+				 */
+				// PAW
+				//tableAlias = getTableAlias(null, useOuterJoins, pathName, null);
+				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;
+	}
+
+//	/**
+//	 * 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;
+//	}

      /**
       * Answer the column name for alias and path info<br>
@@ -418,9 +496,11 @@
       * @param buf
       * @return
       */
-    protected boolean appendColName(String attr, boolean useOuterJoins, 
String aUserAlias, StringBuffer buf)
+	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);
+		AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
aUserAlias, getQuery().getPathClasses());
          TableAlias tableAlias = attrInfo.tableAlias;

          return appendColName(tableAlias, attrInfo.pathInfo, true, buf);
@@ -441,10 +521,10 @@
       * @param buf
       * @return
       */
-    protected boolean appendColName(String attr, String attrAlias, 
boolean useOuterJoins, String aUserAlias,
-            StringBuffer buf)
+	protected boolean appendColName(String attr, String attrAlias, boolean 
useOuterJoins, String aUserAlias,
+			StringBuffer buf)
      {
-        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
aUserAlias);
+        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
aUserAlias, getQuery().getPathClasses());
          TableAlias tableAlias = attrInfo.tableAlias;
          PathInfo pi = attrInfo.pathInfo;

@@ -601,6 +681,8 @@
                      statement.insert(0, "(");
                      statement.append(") AND ");
                  }
+				// PAW
+				m_logger.debug("Building Statement String: " + statement.toString());
                  appendSQLClause(c, statement);
              }
          } // while
@@ -624,7 +706,7 @@
       */
      private void appendBetweenCriteria(TableAlias alias, PathInfo 
pathInfo, BetweenCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());
          appendParameter(c.getValue(), buf);
          buf.append(" AND ");
@@ -654,12 +736,12 @@
       */
      private void appendFieldCriteria(TableAlias alias, PathInfo 
pathInfo, FieldCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());

          if (c.isTranslateField())
          {
-            appendColName((String) c.getValue(), false, c.getAlias(), buf);
+			appendColName((String) c.getValue(), false, c.getAlias(), buf);
          }
          else
          {
@@ -677,7 +759,7 @@
       */
      private void appendInCriteria(TableAlias alias, PathInfo pathInfo, 
InCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());

          if (c.getValue() instanceof Collection)
@@ -710,7 +792,7 @@
       */
      private void appendNullCriteria(TableAlias alias, PathInfo 
pathInfo, NullCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());
      }

@@ -731,7 +813,7 @@
       */
      private void appendSelectionCriteria(TableAlias alias, PathInfo 
pathInfo, SelectionCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());
          appendParameter(c.getValue(), buf);
      }
@@ -744,7 +826,7 @@
       */
      private void appendLikeCriteria(TableAlias alias, PathInfo 
pathInfo, LikeCriteria c, StringBuffer buf)
      {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+		appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
          buf.append(c.getClause());
          appendParameter(c.getValue(), buf);

@@ -815,7 +897,10 @@
              return;
          }

-        AttributeInfo attrInfo = getAttributeInfo((String) 
c.getAttribute(), false, c.getAlias());
+		// PAW
+//		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)
@@ -901,156 +986,318 @@
          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;
-                        }
-                    }
-                }
-            }
-
-            curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
-
-            if (curr == null)
-            {
-                List hintClasses = (List) 
getQuery().getPathClasses().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);
-
-                buildSuperJoinTree(curr, cld, aPath);
-            }
-
-            prev = curr;
-        }
-
-        return curr;
-    }
+	/**
+	 * 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
+	 */
+	// PAW: copied entire getTableAlias(String, boolean, String, String[])
+	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;
+		}
+
+		// PAW
+		//descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, 
getQuery().getPathClasses());
+		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;
+					// PAW
+					//descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, 
getQuery().getPathClasses());
+					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;
+				// PAW
+				//cld = getItemClassDescriptor(cod, attrPath);
+				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
+				// PAW
+				//cld = getItemClassDescriptor(ord, attrPath);
+				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)
+			{
+				// PAW
+				// List hintClasses = (List) getQuery().getPathClasses().get(aPath);
+				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);
+
+				buildSuperJoinTree(curr, cld, aPath);
+			}
+
+			prev = curr;
+		}
+
+		return curr;
+	}
+
+//	/**
+//	 * 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;
+//						}
+//					}
+//				}
+//			}
+//
+//			curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
+//
+//			if (curr == null)
+//			{
+//				List hintClasses = (List) getQuery().getPathClasses().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);
+//
+//				buildSuperJoinTree(curr, cld, aPath);
+//			}
+//
+//			prev = curr;
+//		}
+//
+//		return curr;
+//	}

      /**
       * add a join between two aliases
@@ -1161,13 +1408,17 @@
      private TableAlias createTableAlias(ClassDescriptor aCld, String 
aPath, String aUserAlias, String anOriginalPath,
              List hints)
      {
-        if (aUserAlias == null || !anOriginalPath.equals(aPath))
+    	// PAW
+		//if (aUserAlias == null || !anOriginalPath.equals(aPath))
+		if (aUserAlias == null)
          {
              return createTableAlias(aCld, hints, aPath);
          }
          else
          {
-            return createTableAlias(aCld, hints, aUserAlias);
+        	// PAW
+			//return createTableAlias(aCld, hints, aUserAlias);
+			return createTableAlias(aCld, hints, aUserAlias+aPath);
          }
      }

@@ -1204,13 +1455,15 @@
       */
      private TableAlias createTableAlias(String aTable, String aPath, 
String aUserAlias, String anOriginalPath)
      {
-        if (aUserAlias == null || !anOriginalPath.equals(aPath))
+    	// PAW
+		//if (aUserAlias == null || !anOriginalPath.equals(aPath))
+		if (aUserAlias == null)
          {
              return createTableAlias(aTable, aPath);
          }
          else
          {
-            return createTableAlias(aTable, aUserAlias);
+            return createTableAlias(aTable, aUserAlias+aPath);
          }
      }

@@ -1259,7 +1512,9 @@
          }
          else
          {
-            return getTableAliasForPath(aUserAlias);
+        	// PAW
+			// return getTableAliasForPath(aUserAlias);
+			return getTableAliasForPath(aUserAlias+aPath);
          }
      }

@@ -1272,48 +1527,89 @@
       */
      private TableAlias getTableAliasForPath(String aPath, String 
aUserAlias, String anOriginalPath)
      {
-        if (aUserAlias == null || !anOriginalPath.equals(aPath))
+    	// PAW
+		//if (aUserAlias == null || !anOriginalPath.equals(aPath))
+		if (aUserAlias == null)
          {
              return getTableAliasForPath(aPath);
          }
          else
          {
-            return getTableAliasForPath(aUserAlias);
-        }
-    }
-
-    /**
-     * 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);
-
-    }
+        	// PAW
+            //return getTableAliasForPath(aUserAlias);
+			return getTableAliasForPath(aUserAlias+aPath);
+        }
+    }
+
+	/**
+	 * TODO: add super ClassDescriptor
+	 * answer the ClassDescriptor for itemClass for an 
ObjectReferenceDescriptor
+	 * check optional hint;
+	 */
+	// PAW
+//	private ClassDescriptor 
getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr)
+	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);
+
+	}
+
+//	/**
+//	 * 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);
+//
+//	}

      /**
       * Appends to the statement the ORDER BY clause for the Query
@@ -1536,12 +1832,16 @@
                  // BRJ: do not build join tree for subQuery attribute 

                  if (c.getAttribute() != null && c.getAttribute() 
instanceof String)
                  {
-                    buildJoinTreeForColumn((String) c.getAttribute(), 
useOuterJoin, c.getAlias());
+                	// PAW
+					//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());
+                    // PAW
+					//buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, 
c.getAlias());
+					buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, 
c.getAlias(), c.getPathClasses());
                  }
              }
          }
@@ -1552,17 +1852,21 @@
       * functions and the last segment are removed
       * ie: avg(accounts.amount) -> accounts
       */
-    private void buildJoinTreeForColumn(String aColName, boolean 
useOuterJoin, String aUserAlias)
+    // PAW
+	//private void buildJoinTreeForColumn(String aColName, boolean 
useOuterJoin, String aUserAlias)
+	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)});
+        	// PAW
+			//getTableAlias(pathName.substring(0, sepPos), useOuterJoin, 
aUserAlias, new String[]{pathName
+			//		.substring(sepPos + 1)});
+            getTableAlias(pathName.substring(0, sepPos), useOuterJoin, 
aUserAlias,
+            			  new String[]{pathName.substring(sepPos + 1)}, 
pathClasses);
          }
-
      }

      /**

> Hi Jakob,
> 
> I've done the changes to allow pathClass to be specified per Criteria 
> rather than per QueryByCriteria.  The main change from the user point of 
> view is the addition of the method Criteria#setPathClass().   So the 
> following query is now possible:
> 
> Criteria crit1 = new Criteria();
> crit1.setAlias("alias1");
> crit1.addEqualTo("allBs.c.cAttrib", new String("foo1"));
> crit1.setPathClass("c", C.class); // new: per criteria
> 
> Criteria crit2 = new Criteria();
> crit2.setAlias("alias2");
> crit1.addEqualTo("allBs.c.dAttrib", new String("foo2"));
> crit1.setPathClass("c", C1.class); // new: per criteria
> 
> crit1.addAndCriteria(crit2);
> 
> Query query = new QueryByCriteria(A.class, crit1);
> 
> 
> For backward compatibility, QueryByCriteria#setPathClass() is still 
> available.  What happens is that if no pathClass is specified at a 
> particular Criteria level, the parent Criteria is searched for a 
> pathClass, and so on until the parent Criteria.  If no pathClass is 
> found there, the pathClass of the owning QueryByCriteria is accessed.
> I've created a junit test case to test the new functionality; no errors 
> have been introduced to the existing broker junit tests with these 
> changes (tested with hsqldb).
> 
> I based my changes on the CVS snapshot from 2004/03/14 and notice that 
> as of this today, no changes have been made since then to the java 
> source that I changed.  I've marked my changes in the code by my 
> initials //PAW.  I'd would really like if you could review this code to 
> see if there is anything you see that is questionable.
> 
> I'm not proposing that this should be added before 1.0, but I'd like to 
> get an iteration out there for feedback before I go ahead with phase II: 
>  aliases specified by segment.
> 
> Summary of attached files:
> 
> src files
> o.a.o.b.query.Criteria.java
> o.a.o.b.query.SelectionCriteria.java
> o.a.o.b.query.BetweenCriteria.java
> o.a.o.b.accesslayer.sql.SqlQueryStatement.java
> o.a.o.b.accesslayer.sql.SqlSelectStatement.java
> 
> srcTest files
> ojbTest-schema-pathClass.xml
> repository-junit-pathClass.xml
> o.a.o.b.query.A.java
> o.a.o.b.query.B.java
> o.a.o.b.query.C.java
> o.a.o.b.query.C1.java
> o.a.o.b.query.D.java
> o.a.o.b.query.PathClassTest.java
> 
> test class object model:
> 
> A-1------M-B-1------M-C-1------1-D
>                       |
>                       | (subclass)
>                       |
>                       C1
> 
> Thanks,
> 
> Phil



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Re: Per-criteria pathClass [was ojb-user: Query casts] 2 of 2

Posted by Jakob Braeuchi <jb...@gmx.ch>.
hi phil,

thanks for the patch. i applied it to revision 1.70 and i only get differences 
in some methods:


Index: SqlQueryStatement.java
===================================================================
RCS file: 
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v
retrieving revision 1.70
diff -u -r1.70 SqlQueryStatement.java
--- SqlQueryStatement.java	27 Mar 2004 20:57:23 -0000	1.70
+++ SqlQueryStatement.java	28 Mar 2004 09:23:19 -0000
@@ -444,7 +444,7 @@
      protected boolean appendColName(String attr, String attrAlias, boolean 
useOuterJoins, String aUserAlias,
              StringBuffer buf)
      {
-        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias);
+        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
aUserAlias, getQuery().getPathClasses());
          TableAlias tableAlias = attrInfo.tableAlias;
          PathInfo pi = attrInfo.pathInfo;

@@ -601,6 +601,8 @@
                      statement.insert(0, "(");
                      statement.append(") AND ");
                  }
+                // PAW
+                m_logger.debug("Building Statement String: " + 
statement.toString());
                  appendSQLClause(c, statement);
              }
          } // while
@@ -1168,13 +1170,17 @@
      private TableAlias createTableAlias(ClassDescriptor aCld, String aPath, 
String aUserAlias, String anOriginalPath,
              List hints)
      {
-        if (aUserAlias == null || !anOriginalPath.equals(aPath))
+        // PAW
+        //if (aUserAlias == null || !anOriginalPath.equals(aPath))
+        if (aUserAlias == null)
          {
              return createTableAlias(aCld, hints, aPath);
          }
          else
          {
-            return createTableAlias(aCld, hints, aUserAlias);
+            // PAW
+            //return createTableAlias(aCld, hints, aUserAlias);
+            return createTableAlias(aCld, hints, aUserAlias+aPath);
          }
      }

@@ -1211,13 +1217,15 @@
       */
      private TableAlias createTableAlias(String aTable, String aPath, String 
aUserAlias, String anOriginalPath)
      {
-        if (aUserAlias == null || !anOriginalPath.equals(aPath))
+        // PAW
+        //if (aUserAlias == null || !anOriginalPath.equals(aPath))
+        if (aUserAlias == null)
          {
              return createTableAlias(aTable, aPath);
          }
          else
          {
-            return createTableAlias(aTable, aUserAlias);
+            return createTableAlias(aTable, aUserAlias+aPath);
          }
      }

@@ -1266,7 +1274,9 @@
          }
          else
          {
-            return getTableAliasForPath(aUserAlias);
+            // PAW
+            // return getTableAliasForPath(aUserAlias);
+            return getTableAliasForPath(aUserAlias+aPath);
          }
      }


your patch is a lot bigger, so what's going wrong here ?
btw i do not have your other patched classes you mentioned in the post.

jakob

Phil Warrick wrote:
> Hi,
> 
> I will have to learn to work with patches it seems. 
> SqlQueryStatement.java was too long, so here is the patch.  Note that my 
> changes were based on version 1.68 and we're up to 1.70 now as of a few 
> minutes ago :)
> 
> Phil
> 
> 
> 
> Index: SqlQueryStatement.java
> ===================================================================
> RCS file: 
> /home/cvspublic/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v 
> 
> retrieving revision 1.68
> diff -u -r1.68 SqlQueryStatement.java
> --- SqlQueryStatement.java    11 Mar 2004 18:16:08 -0000    1.68
> +++ SqlQueryStatement.java    27 Mar 2004 21:25:10 -0000
> @@ -114,7 +114,9 @@
>          }
>          else
>          {
> -            m_search = 
> getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null);
> +            // PAW
> +            //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 +141,147 @@
>          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
> +     * @return ColumnInfo
> +     */
> +    // PAW
> +    // Todo: merge with other original getAttributeInfo(...)
> +    //protected AttributeInfo getAttributeInfo(String attr, boolean 
> useOuterJoins, String aUserAlias)
> +    protected AttributeInfo getAttributeInfo(String attr, boolean 
> useOuterJoins, String aUserAlias, Map pathClasses)
> +    //protected AttributeInfo getAttributeInfo(SelectionCriteria crit, 
> boolean useOuterJoins)
> +    {
> +        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())};
> +            // PAW: is pathClasses the correct argument to pass to parent?
> +            //return 
> m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, 
> aUserAlias, pathClasses);
> +            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)};
> +
> +            // PAW
> +            //tableAlias = getTableAlias(pathName, useOuterJoins, 
> aUserAlias, fieldNameRef);
> +            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
> +                 */
> +                // PAW
> +                //tableAlias = getTableAlias(null, useOuterJoins, 
> pathName, null);
> +                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;
> +    }
> +
> +//    /**
> +//     * 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;
> +//    }
> 
>      /**
>       * Answer the column name for alias and path info<br>
> @@ -418,9 +496,11 @@
>       * @param buf
>       * @return
>       */
> -    protected boolean appendColName(String attr, boolean useOuterJoins, 
> String aUserAlias, StringBuffer buf)
> +    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);
> +        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
> aUserAlias, getQuery().getPathClasses());
>          TableAlias tableAlias = attrInfo.tableAlias;
> 
>          return appendColName(tableAlias, attrInfo.pathInfo, true, buf);
> @@ -441,10 +521,10 @@
>       * @param buf
>       * @return
>       */
> -    protected boolean appendColName(String attr, String attrAlias, 
> boolean useOuterJoins, String aUserAlias,
> -            StringBuffer buf)
> +    protected boolean appendColName(String attr, String attrAlias, 
> boolean useOuterJoins, String aUserAlias,
> +            StringBuffer buf)
>      {
> -        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
> aUserAlias);
> +        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, 
> aUserAlias, getQuery().getPathClasses());
>          TableAlias tableAlias = attrInfo.tableAlias;
>          PathInfo pi = attrInfo.pathInfo;
> 
> @@ -601,6 +681,8 @@
>                      statement.insert(0, "(");
>                      statement.append(") AND ");
>                  }
> +                // PAW
> +                m_logger.debug("Building Statement String: " + 
> statement.toString());
>                  appendSQLClause(c, statement);
>              }
>          } // while
> @@ -624,7 +706,7 @@
>       */
>      private void appendBetweenCriteria(TableAlias alias, PathInfo 
> pathInfo, BetweenCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
>          appendParameter(c.getValue(), buf);
>          buf.append(" AND ");
> @@ -654,12 +736,12 @@
>       */
>      private void appendFieldCriteria(TableAlias alias, PathInfo 
> pathInfo, FieldCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
> 
>          if (c.isTranslateField())
>          {
> -            appendColName((String) c.getValue(), false, c.getAlias(), 
> buf);
> +            appendColName((String) c.getValue(), false, c.getAlias(), 
> buf);
>          }
>          else
>          {
> @@ -677,7 +759,7 @@
>       */
>      private void appendInCriteria(TableAlias alias, PathInfo pathInfo, 
> InCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
> 
>          if (c.getValue() instanceof Collection)
> @@ -710,7 +792,7 @@
>       */
>      private void appendNullCriteria(TableAlias alias, PathInfo 
> pathInfo, NullCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
>      }
> 
> @@ -731,7 +813,7 @@
>       */
>      private void appendSelectionCriteria(TableAlias alias, PathInfo 
> pathInfo, SelectionCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
>          appendParameter(c.getValue(), buf);
>      }
> @@ -744,7 +826,7 @@
>       */
>      private void appendLikeCriteria(TableAlias alias, PathInfo 
> pathInfo, LikeCriteria c, StringBuffer buf)
>      {
> -        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
> +        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
>          buf.append(c.getClause());
>          appendParameter(c.getValue(), buf);
> 
> @@ -815,7 +897,10 @@
>              return;
>          }
> 
> -        AttributeInfo attrInfo = getAttributeInfo((String) 
> c.getAttribute(), false, c.getAlias());
> +        // PAW
> +//        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)
> @@ -901,156 +986,318 @@
>          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;
> -                        }
> -                    }
> -                }
> -            }
> -
> -            curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
> -
> -            if (curr == null)
> -            {
> -                List hintClasses = (List) 
> getQuery().getPathClasses().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);
> -
> -                buildSuperJoinTree(curr, cld, aPath);
> -            }
> -
> -            prev = curr;
> -        }
> -
> -        return curr;
> -    }
> +    /**
> +     * 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
> +     */
> +    // PAW: copied entire getTableAlias(String, boolean, String, String[])
> +    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;
> +        }
> +
> +        // PAW
> +        //descriptors = 
> getRoot().cld.getAttributeDescriptorsForPath(aPath, 
> getQuery().getPathClasses());
> +        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;
> +                    // PAW
> +                    //descriptors = 
> prev.cld.getAttributeDescriptorsForPath(aPath, 
> getQuery().getPathClasses());
> +                    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;
> +                // PAW
> +                //cld = getItemClassDescriptor(cod, attrPath);
> +                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
> +                // PAW
> +                //cld = getItemClassDescriptor(ord, attrPath);
> +                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)
> +            {
> +                // PAW
> +                // List hintClasses = (List) 
> getQuery().getPathClasses().get(aPath);
> +                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);
> +
> +                buildSuperJoinTree(curr, cld, aPath);
> +            }
> +
> +            prev = curr;
> +        }
> +
> +        return curr;
> +    }
> +
> +//    /**
> +//     * 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;
> +//                        }
> +//                    }
> +//                }
> +//            }
> +//
> +//            curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
> +//
> +//            if (curr == null)
> +//            {
> +//                List hintClasses = (List) 
> getQuery().getPathClasses().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);
> +//
> +//                buildSuperJoinTree(curr, cld, aPath);
> +//            }
> +//
> +//            prev = curr;
> +//        }
> +//
> +//        return curr;
> +//    }
> 
>      /**
>       * add a join between two aliases
> @@ -1161,13 +1408,17 @@
>      private TableAlias createTableAlias(ClassDescriptor aCld, String 
> aPath, String aUserAlias, String anOriginalPath,
>              List hints)
>      {
> -        if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        // PAW
> +        //if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        if (aUserAlias == null)
>          {
>              return createTableAlias(aCld, hints, aPath);
>          }
>          else
>          {
> -            return createTableAlias(aCld, hints, aUserAlias);
> +            // PAW
> +            //return createTableAlias(aCld, hints, aUserAlias);
> +            return createTableAlias(aCld, hints, aUserAlias+aPath);
>          }
>      }
> 
> @@ -1204,13 +1455,15 @@
>       */
>      private TableAlias createTableAlias(String aTable, String aPath, 
> String aUserAlias, String anOriginalPath)
>      {
> -        if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        // PAW
> +        //if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        if (aUserAlias == null)
>          {
>              return createTableAlias(aTable, aPath);
>          }
>          else
>          {
> -            return createTableAlias(aTable, aUserAlias);
> +            return createTableAlias(aTable, aUserAlias+aPath);
>          }
>      }
> 
> @@ -1259,7 +1512,9 @@
>          }
>          else
>          {
> -            return getTableAliasForPath(aUserAlias);
> +            // PAW
> +            // return getTableAliasForPath(aUserAlias);
> +            return getTableAliasForPath(aUserAlias+aPath);
>          }
>      }
> 
> @@ -1272,48 +1527,89 @@
>       */
>      private TableAlias getTableAliasForPath(String aPath, String 
> aUserAlias, String anOriginalPath)
>      {
> -        if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        // PAW
> +        //if (aUserAlias == null || !anOriginalPath.equals(aPath))
> +        if (aUserAlias == null)
>          {
>              return getTableAliasForPath(aPath);
>          }
>          else
>          {
> -            return getTableAliasForPath(aUserAlias);
> -        }
> -    }
> -
> -    /**
> -     * 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);
> -
> -    }
> +            // PAW
> +            //return getTableAliasForPath(aUserAlias);
> +            return getTableAliasForPath(aUserAlias+aPath);
> +        }
> +    }
> +
> +    /**
> +     * TODO: add super ClassDescriptor
> +     * answer the ClassDescriptor for itemClass for an 
> ObjectReferenceDescriptor
> +     * check optional hint;
> +     */
> +    // PAW
> +//    private ClassDescriptor 
> getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr)
> +    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);
> +
> +    }
> +
> +//    /**
> +//     * 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);
> +//
> +//    }
> 
>      /**
>       * Appends to the statement the ORDER BY clause for the Query
> @@ -1536,12 +1832,16 @@
>                  // BRJ: do not build join tree for subQuery attribute
>                  if (c.getAttribute() != null && c.getAttribute() 
> instanceof String)
>                  {
> -                    buildJoinTreeForColumn((String) c.getAttribute(), 
> useOuterJoin, c.getAlias());
> +                    // PAW
> +                    //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());
> +                    // PAW
> +                    //buildJoinTreeForColumn((String) cc.getValue(), 
> useOuterJoin, c.getAlias());
> +                    buildJoinTreeForColumn((String) cc.getValue(), 
> useOuterJoin, c.getAlias(), c.getPathClasses());
>                  }
>              }
>          }
> @@ -1552,17 +1852,21 @@
>       * functions and the last segment are removed
>       * ie: avg(accounts.amount) -> accounts
>       */
> -    private void buildJoinTreeForColumn(String aColName, boolean 
> useOuterJoin, String aUserAlias)
> +    // PAW
> +    //private void buildJoinTreeForColumn(String aColName, boolean 
> useOuterJoin, String aUserAlias)
> +    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)});
> +            // PAW
> +            //getTableAlias(pathName.substring(0, sepPos), 
> useOuterJoin, aUserAlias, new String[]{pathName
> +            //        .substring(sepPos + 1)});
> +            getTableAlias(pathName.substring(0, sepPos), useOuterJoin, 
> aUserAlias,
> +                          new String[]{pathName.substring(sepPos + 1)}, 
> pathClasses);
>          }
> -
>      }
> 
>      /**
> 
>> Hi Jakob,
>>
>> I've done the changes to allow pathClass to be specified per Criteria 
>> rather than per QueryByCriteria.  The main change from the user point 
>> of view is the addition of the method Criteria#setPathClass().   So 
>> the following query is now possible:
>>
>> Criteria crit1 = new Criteria();
>> crit1.setAlias("alias1");
>> crit1.addEqualTo("allBs.c.cAttrib", new String("foo1"));
>> crit1.setPathClass("c", C.class); // new: per criteria
>>
>> Criteria crit2 = new Criteria();
>> crit2.setAlias("alias2");
>> crit1.addEqualTo("allBs.c.dAttrib", new String("foo2"));
>> crit1.setPathClass("c", C1.class); // new: per criteria
>>
>> crit1.addAndCriteria(crit2);
>>
>> Query query = new QueryByCriteria(A.class, crit1);
>>
>>
>> For backward compatibility, QueryByCriteria#setPathClass() is still 
>> available.  What happens is that if no pathClass is specified at a 
>> particular Criteria level, the parent Criteria is searched for a 
>> pathClass, and so on until the parent Criteria.  If no pathClass is 
>> found there, the pathClass of the owning QueryByCriteria is accessed.
>> I've created a junit test case to test the new functionality; no 
>> errors have been introduced to the existing broker junit tests with 
>> these changes (tested with hsqldb).
>>
>> I based my changes on the CVS snapshot from 2004/03/14 and notice that 
>> as of this today, no changes have been made since then to the java 
>> source that I changed.  I've marked my changes in the code by my 
>> initials //PAW.  I'd would really like if you could review this code 
>> to see if there is anything you see that is questionable.
>>
>> I'm not proposing that this should be added before 1.0, but I'd like 
>> to get an iteration out there for feedback before I go ahead with 
>> phase II:  aliases specified by segment.
>>
>> Summary of attached files:
>>
>> src files
>> o.a.o.b.query.Criteria.java
>> o.a.o.b.query.SelectionCriteria.java
>> o.a.o.b.query.BetweenCriteria.java
>> o.a.o.b.accesslayer.sql.SqlQueryStatement.java
>> o.a.o.b.accesslayer.sql.SqlSelectStatement.java
>>
>> srcTest files
>> ojbTest-schema-pathClass.xml
>> repository-junit-pathClass.xml
>> o.a.o.b.query.A.java
>> o.a.o.b.query.B.java
>> o.a.o.b.query.C.java
>> o.a.o.b.query.C1.java
>> o.a.o.b.query.D.java
>> o.a.o.b.query.PathClassTest.java
>>
>> test class object model:
>>
>> A-1------M-B-1------M-C-1------1-D
>>                       |
>>                       | (subclass)
>>                       |
>>                       C1
>>
>> Thanks,
>>
>> Phil
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-dev-help@db.apache.org
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org